paint-brush
Použití stratifikační metody pro experimentální analýzupodle@nataliaogneva
33,138 čtení
33,138 čtení

Použití stratifikační metody pro experimentální analýzu

podle Natalia Ogneva8m2024/04/19
Read on Terminal Reader
Read this story w/o Javascript

Příliš dlouho; Číst

Stratifikované vzorkování je výkonná technika pro zvýšení efektivity experimentu a metrické citlivosti při analýze dat. Seskupením publika a jeho rozdělením podle konkrétních vah můžete optimalizovat experimenty, snížit rozptyl a zvýšit spolehlivost výsledků.

Company Mentioned

Mention Thumbnail
featured image - Použití stratifikační metody pro experimentální analýzu
Natalia Ogneva HackerNoon profile picture
0-item


Jakýkoli experiment zahrnuje kompromis mezi rychlými výsledky a metrickou citlivostí. Pokud je zvolená metrika z hlediska rozptylu široká, musíme dlouho čekat, abychom zajistili přesnost výsledků experimentu. Podívejme se na jednu metodu, která pomůže analytikům posílit jejich experimenty, aniž by ztratili příliš mnoho času nebo metrické citlivosti.


Formulace problému

Předpokládejme, že provedeme standardní experiment, abychom otestovali nový algoritmus hodnocení, přičemž primární metrikou je délka návštěvy. Kromě toho si uvědomte, že naše publikum lze zhruba rozdělit do tří skupin: 1 milion teenagerů, 2 miliony uživatelů ve věku 18–45 let a 3 miliony uživatelů ve věku 45 a více let. Reakce na nový algoritmus hodnocení by se mezi těmito skupinami publika výrazně lišila. Tato široká variace snižuje citlivost metriky.


Jinými slovy, populaci lze rozdělit do tří vrstev, které jsou popsány následovně:


Řekněme, že každá součástka má normální rozdělení. Potom má hlavní metrika pro populaci také normální rozdělení.

Stratifikační metoda

Náhodně rozdělujeme všechny uživatele z populace v klasickém designu experimentu, aniž bychom zohledňovali rozdíly mezi našimi uživateli. Uvažujeme tedy vzorek s následující očekávanou hodnotou a rozptylem.


Dalším způsobem je náhodné rozdělení uvnitř každé vrstvy podle váhy vrstvy v obecné populaci.

V tomto případě jsou očekávaná hodnota a rozptyl následující.


Očekávaná hodnota je stejná jako u prvního výběru. Rozptyl je však menší, což zaručuje vyšší metrickou citlivost.

Nyní se podívejme na Neymanovu metodu . Navrhují rozdělit uživatele náhodně uvnitř každé vrstvy s konkrétními váhami.

Očekávaná hodnota a rozptyl se tedy v tomto případě rovnají následujícímu.

Očekávaná hodnota se rovná očekávané hodnotě v prvním případě asymptoticky. Rozptyl je však mnohem menší.

Empirické testování

Teoreticky jsme prokázali účinnost této metody. Pojďme simulovat vzorky a empiricky otestovat metodu stratifikace.

Uvažujme tři případy:

  • všechny vrstvy se stejnými prostředky a rozdíly,
  • všechny vrstvy s různými prostředky a stejnými rozdíly,
  • všechny vrstvy se stejnými prostředky a různými rozptyly.

Použijeme všechny tři metody ve všech případech a vyneseme histogram a boxplot pro jejich porovnání.

Příprava kódu

Nejprve vytvořte třídu v Pythonu, která simuluje naši obecnou populaci sestávající ze tří vrstev.

 class GeneralPopulation: def __init__(self, means: [float], stds: [float], sizes: [int], random_state: int = 15 ): """ Initializes our General Population and saves the given distributions :param means: List of expectations for normal distributions :param stds: List of standard deviations for normal distributions :param sizes: How many objects will be in each strata :param random_state: Parameter fixing randomness. Needed so that when conducting experiment repeatedly with the same input parameters, the results remained the same """ self.strats = [st.norm(mean, std) for mean, std in zip(means, stds)] self._sample(sizes) self.random_state = random_state def _sample(self, sizes): """Creates a general population sample as a mixture of strata :param sizes: List with sample sizes of the corresponding normal distributions """ self.strats_samples = [rv.rvs(size) for rv, size in zip(self.strats, sizes)] self.general_samples = np.hstack(self.strats_samples) self.N = self.general_samples.shape[0] # number of strata self.count_strats = len(sizes) # ratios for every strata in GP self.ws = [size/self.N for size in sizes] # ME and Std for GP self.m = np.mean(self.general_samples) self.sigma = np.std(self.general_samples) # ME and std for all strata self.ms = [np.mean(strat_sample) for strat_sample in self.strats_samples] self.sigmas = [np.std(strat_sample) for strat_sample in self.strats_samples]


Poté přidáme funkce pro tři metody vzorkování popsané v teoretické části.

 def random_subsampling(self, size): """Creates a random subset of the entire population :param sizes: subsample size """ rc = np.random.choice(self.general_samples, size=size) return rc def proportional_subsampling(self, size): """Creates a subsample with the number of elements, proportional shares of strata :param sizes: subsample size """ self.strats_size_proport = [int(np.floor(size*w)) for w in self.ws] rc = [] for k in range(len(self.strats_size_proport)): rc.append(np.random.choice(self.strats_samples[k], size=self.strats_size_proport[k])) return rc def optimal_subsampling(self, size): """Creates a subsample with the optimal number of elements relative to strata :param sizes: subsample size """ sum_denom = 0 for k in range(self.count_strats): sum_denom += self.ws[k] * self.sigmas[k] self.strats_size_optimal = [int(np.floor((size*w*sigma)/sum_denom)) for w, sigma in zip(self.ws, self.sigmas)] if 0 in self.strats_size_optimal: raise ValueError('Strats size is 0, please change variance of smallest strat!') rc = [] for k in range(len(self.strats_size_optimal)): rc.append(np.random.choice(self.strats_samples[k], size=self.strats_size_optimal[k])) return rc


Také pro empirickou část vždy potřebujeme funkci pro simulaci procesu experimentu.

 def run_experiments(self, n_sub, subsampling_method, n_experiments=1000): """Conducts a series of experiments and saves the results :param n_sub: size of sample :param subsampling_method: method for creating a subsample :param n_experiments: number of experiment starts """ means_s = [] if(len(self.general_samples)<100): n_sub = 20 if(subsampling_method == 'random_subsampling'): for n in range(n_experiments): rc = self.random_subsampling(n_sub) mean = rc.sum()/len(rc) means_s.append(mean) else: for n in range(n_experiments): if(subsampling_method == 'proportional_subsampling'): rc = self.proportional_subsampling(n_sub) elif(subsampling_method == 'optimal_subsampling'): rc = self.optimal_subsampling(n_sub) strats_mean = [] for k in range(len(rc)): strats_mean.append(sum(rc[k])/len(rc[k])) # Mean for a mixture means_s.append(sum([w_k*mean_k for w_k, mean_k in zip(self.ws, strats_mean)])) return means_s


Výsledky simulace

Pokud se podíváme na obecnou populaci, kde všechny naše vrstvy mají stejné hodnoty a rozptyly, očekává se, že výsledky všech tří metod budou víceméně stejné.

Různé průměry a stejné rozdíly přinesly zajímavější výsledky. Použití stratifikace dramaticky snižuje rozptyl.

V případech se stejnými průměry a různými rozptyly vidíme u Neymanovy metody snížení rozptylu.

Závěr

Nyní můžete použít metodu stratifikace, abyste snížili metrický rozptyl a podpořili experiment, pokud seskupíte své publikum a technicky je náhodně rozdělíte do každého shluku se specifickými váhami!