![Search icon](https://hackernoon.imgix.net/search-new.png?w=19&h=19)
Orice experiment implică un compromis între rezultatele rapide și sensibilitatea metricului. Dacă valoarea aleasă este largă în ceea ce privește varianța, trebuie să așteptăm mult timp pentru a ne asigura că rezultatele experimentului sunt exacte. Să luăm în considerare o metodă care să-i ajute pe analiști să-și dezvolte experimentele fără a pierde prea mult timp sau sensibilitatea metrică.
Să presupunem că efectuăm un experiment standard pentru a testa un nou algoritm de clasare, cu durata sesiunii ca măsură principală. În plus, luați în considerare că publicul nostru poate fi clasificat aproximativ în trei grupuri: 1 milion de adolescenți, 2 milioane de utilizatori cu vârsta cuprinsă între 18-45 de ani și 3 milioane de utilizatori cu vârsta de 45 de ani și peste. Răspunsul la un nou algoritm de clasare ar varia semnificativ între aceste grupuri de public. Această variație largă reduce sensibilitatea metricii.
Cu alte cuvinte, populația poate fi împărțită în trei straturi, descrise astfel:
Să presupunem că fiecare componentă are o distribuție normală. Apoi, metrica principală pentru populație are și o distribuție normală.
Împărțim aleatoriu toți utilizatorii din populație într-un design de experiment clasic, fără a lua în considerare diferențele dintre utilizatorii noștri. Astfel, luăm în considerare eșantionul cu următoarea valoare așteptată și varianță.
O altă modalitate este împărțirea aleatorie în interiorul fiecărui strat în funcție de ponderea stratului în populația generală.
În acest caz, valoarea așteptată și varianța sunt următoarele.
Valoarea așteptată este aceeași ca în prima selecție. Cu toate acestea, varianța este mai mică, ceea ce garantează o sensibilitate metrică mai mare.
Acum, să luăm în considerare metoda lui Neyman . Ei sugerează împărțirea aleatorie a utilizatorilor în fiecare strat cu greutăți specifice.
Deci, valoarea așteptată și varianța sunt egale cu următoarele în acest caz.
Valoarea așteptată este egală cu valoarea așteptată în primul caz asimptotic. Cu toate acestea, variația este mult mai mică.
Am demonstrat teoretic eficiența acestei metode. Să simulăm eșantioane și să testăm empiric metoda de stratificare.
Să luăm în considerare trei cazuri:
Vom aplica toate cele trei metode în toate cazurile și vom reprezenta o histogramă și un diagramă cu casete pentru a le compara.
Mai întâi, să creăm o clasă în Python care simulează populația noastră generală constând din trei straturi.
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]
Apoi, să adăugăm funcții pentru cele trei metode de eșantionare descrise în partea teoretică.
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
De asemenea, pentru partea empirică, avem întotdeauna nevoie de o funcție pentru simularea procesului experimental.
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
Dacă ne uităm la populația generală, unde toate straturile noastre au aceleași valori și varianțe, se așteaptă ca rezultatele tuturor celor trei metode să fie mai mult sau mai puțin egale.
Mijloace diferite și variații egale au obținut rezultate mai interesante. Utilizarea stratificării reduce dramatic varianța.
În cazurile cu medii egale și varianțe diferite, vedem o reducere a varianței în metoda lui Neyman.
Acum, puteți aplica metoda de stratificare pentru a reduce varianța valorii și pentru a stimula experimentul dacă vă grupați publicul și le împărțiți din punct de vedere tehnic în mod aleatoriu în fiecare grup cu ponderi specifice!