paint-brush
Brug af stratificeringsmetoden til eksperimentanalysenved@nataliaogneva
33,138 aflæsninger
33,138 aflæsninger

Brug af stratificeringsmetoden til eksperimentanalysen

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

For langt; At læse

Stratificeret sampling er en kraftfuld teknik til at øge eksperimenteffektiviteten og metrisk følsomhed i dataanalyse. Ved at gruppere dit publikum og opdele dem med specifikke vægte kan du optimere eksperimenter, reducere variansen og forbedre resultaternes pålidelighed.

Company Mentioned

Mention Thumbnail
featured image - Brug af stratificeringsmetoden til eksperimentanalysen
Natalia Ogneva HackerNoon profile picture
0-item


Ethvert eksperiment involverer en afvejning mellem hurtige resultater og metrisk følsomhed. Hvis den valgte metrik er bred med hensyn til varians, skal vi vente længe for at sikre, at eksperimentets resultater er nøjagtige. Lad os overveje en metode til at hjælpe analytikere med at booste deres eksperimenter uden at miste for meget tid eller metrisk følsomhed.


Problemformulering

Antag, at vi udfører et standardeksperiment for at teste en ny rangeringsalgoritme med sessionslængde som den primære metrik. Overvej desuden, at vores publikum groft kan kategoriseres i tre grupper: 1 million teenagere, 2 millioner brugere i alderen 18-45 og 3 millioner brugere på 45 år og derover. Svaret på en ny rangeringsalgoritme vil variere betydeligt blandt disse målgrupper. Denne brede variation reducerer metrikkens følsomhed.


Befolkningen kan med andre ord opdeles i tre lag, beskrevet i det følgende:


Lad os sige, at hver komponent har en normalfordeling. Så har hovedmetrikken for befolkningen også en normalfordeling.

Stratificeringsmetode

Vi opdeler tilfældigt alle brugere fra befolkningen i et klassisk eksperimentdesign uden at tage hensyn til forskellene mellem vores brugere. Derfor betragter vi stikprøven med følgende forventede værdi og varians.


En anden måde er at opdele tilfældigt inden for hvert strat i henhold til vægten af strat i den generelle befolkning.

I dette tilfælde er den forventede værdi og varians følgende.


Den forventede værdi er den samme som i det første valg. Variansen er dog mindre, hvilket garanterer højere metrisk følsomhed.

Lad os nu overveje Neymans metode . De foreslår at opdele brugere tilfældigt inden for hver strat med specifikke vægte.

Så den forventede værdi og varians er lig med følgende i dette tilfælde.

Den forventede værdi er lig med den forventede værdi i det første tilfælde asymptotisk. Afvigelsen er dog meget mindre.

Empirisk test

Vi har bevist effektiviteten af denne metode teoretisk. Lad os simulere prøver og teste stratificeringsmetoden empirisk.

Lad os overveje tre tilfælde:

  • alle strats med lige midler og varianser,
  • alle strats med forskellige midler og lige varianser,
  • alle strats med lige midler og forskellige varianser.

Vi vil anvende alle tre metoder i alle tilfælde og plotte et histogram og et boxplot for at sammenligne dem.

Kode forberedelse

Lad os først oprette en klasse i Python, der simulerer vores generelle befolkning bestående af tre strats.

 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]


Lad os derefter tilføje funktioner til de tre prøveudtagningsmetoder, der er beskrevet i den teoretiske del.

 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


Også for den empiriske del har vi altid brug for en funktion til at simulere eksperimentprocessen.

 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


Simuleringsresultater

Hvis vi ser på den generelle befolkning, hvor alle vores strats har de samme værdier og varianser, forventes resultaterne af alle tre metoder at være nogenlunde ens.

Forskellige midler og lige store varianser opnåede mere spændende resultater. Brug af stratificering reducerer variansen dramatisk.

I tilfælde med lige midler og forskellige varianser ser vi en variansreduktion i Neymans metode.

Konklusion

Nu kan du anvende stratificeringsmetoden til at reducere den metriske varians og booste eksperimentet, hvis du grupperer dit publikum og teknisk deler dem tilfældigt i hver klynge med specifikke vægte!