paint-brush
Användning av stratifieringsmetoden för experimentanalysenförbi@nataliaogneva
33,172 avläsningar
33,172 avläsningar

Användning av stratifieringsmetoden för experimentanalysen

förbi Natalia Ogneva8m2024/04/19
Read on Terminal Reader
Read this story w/o Javascript

För länge; Att läsa

Stratifierad sampling är en kraftfull teknik för att öka experimenteffektiviteten och metrisk känslighet i dataanalys. Genom att gruppera din publik och dela upp dem med specifika vikter kan du optimera experiment, minska variansen och förbättra resultatets tillförlitlighet.

Company Mentioned

Mention Thumbnail
featured image - Användning av stratifieringsmetoden för experimentanalysen
Natalia Ogneva HackerNoon profile picture
0-item


Varje experiment innebär en avvägning mellan snabba resultat och metrisk känslighet. Om det valda måttet är stort när det gäller varians måste vi vänta länge för att säkerställa att experimentets resultat är korrekta. Låt oss överväga en metod för att hjälpa analytiker att öka sina experiment utan att förlora för mycket tid eller metrisk känslighet.


Problemformulering

Anta att vi genomför ett standardexperiment för att testa en ny rankningsalgoritm, med sessionslängd som primärt mått. Tänk också på att vår publik grovt sett kan delas in i tre grupper: 1 miljon tonåringar, 2 miljoner användare i åldern 18–45 och 3 miljoner användare i åldern 45 och uppåt. Svaret på en ny rankningsalgoritm skulle variera avsevärt mellan dessa publikgrupper. Denna stora variation minskar känsligheten hos metriken.


Befolkningen kan med andra ord delas in i tre skikt, som beskrivs nedan:


Låt oss säga att varje komponent har en normalfördelning. Sedan har huvudmåttet för befolkningen också en normalfördelning.

Stratifieringsmetod

Vi delar slumpmässigt in alla användare från befolkningen i en klassisk experimentdesign utan att ta hänsyn till skillnaderna mellan våra användare. Därför betraktar vi provet med följande förväntade värde och varians.


Ett annat sätt är att slumpmässigt dela in varje strat efter vikten av strat i den allmänna befolkningen.

I det här fallet är det förväntade värdet och variansen följande.


Det förväntade värdet är detsamma som i det första valet. Variansen är dock mindre, vilket garanterar högre metrisk känslighet.

Låt oss nu överväga Neymans metod . De föreslår att användarna slumpmässigt delas in i varje strat med specifika vikter.

Så det förväntade värdet och variansen är lika med följande i detta fall.

Förväntningsvärdet är lika med det förväntade värdet i det första fallet asymptotiskt. Variansen är dock mycket mindre.

Empiriska tester

Vi har bevisat effektiviteten av denna metod teoretiskt. Låt oss simulera prover och testa stratifieringsmetoden empiriskt.

Låt oss överväga tre fall:

  • alla strats med lika medel och varianser,
  • alla strats med olika medel och lika varianser,
  • alla strats med lika medel och olika varianser.

Vi kommer att tillämpa alla tre metoderna i alla fall och rita ett histogram och boxplot för att jämföra dem.

Kodförberedelse

Låt oss först skapa en klass i Python som simulerar vår allmänna befolkning bestående av 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]


Låt oss sedan lägga till funktioner för de tre provtagningsmetoderna som beskrivs i den teoretiska delen.

 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


Dessutom, för den empiriska delen, behöver vi alltid en funktion för att simulera experimentprocessen.

 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


Simuleringsresultat

Om vi tittar på den allmänna befolkningen, där alla våra strats har samma värden och varianser, förväntas resultaten av alla tre metoderna vara mer eller mindre lika.

Olika medel och lika variationer fick mer spännande resultat. Att använda stratifiering minskar variansen dramatiskt.

I fall med lika medel och olika varianser ser vi en variansminskning i Neymans metod.

Slutsats

Nu kan du använda stratifieringsmetoden för att minska den metriska variansen och öka experimentet om du grupperar din publik och tekniskt delar upp dem slumpmässigt i varje kluster med specifika vikter!