paint-brush
Використання методу стратифікації для аналізу експериментуза@nataliaogneva
33,166 показання
33,166 показання

Використання методу стратифікації для аналізу експерименту

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

Надто довго; Читати

Стратифікована вибірка є потужною технікою для підвищення ефективності експерименту та чутливості показників при аналізі даних. Згрупувавши свою аудиторію та розділивши її за певними вагами, ви можете оптимізувати експерименти, зменшити дисперсію та підвищити надійність результатів.

Company Mentioned

Mention Thumbnail
featured image - Використання методу стратифікації для аналізу експерименту
Natalia Ogneva HackerNoon profile picture
0-item


Будь-який експеримент передбачає компроміс між швидкими результатами та чутливістю показників. Якщо обрана метрика є широкою з точки зору дисперсії, ми повинні чекати тривалий час, щоб переконатися, що результати експерименту точні. Давайте розглянемо один метод, який допоможе аналітикам покращити свої експерименти, не втрачаючи зайвого часу чи чутливості показників.


Формулювання проблеми

Припустімо, ми проводимо стандартний експеримент, щоб перевірити новий алгоритм ранжирування, використовуючи тривалість сеансу як основний показник. Крім того, візьміть до уваги, що нашу аудиторію можна умовно розділити на три групи: 1 мільйон підлітків, 2 мільйони користувачів віком від 18 до 45 років і 3 мільйони користувачів віком від 45 років. Відповідь на новий алгоритм ранжирування суттєво різниться серед цих груп аудиторії. Така широка варіація знижує чутливість метрики.


Іншими словами, населення можна розділити на три прошарки, описані наступним чином:


Припустимо, що кожен компонент має нормальний розподіл. Тоді основний показник сукупності також має нормальний розподіл.

Метод стратифікації

Ми випадковим чином поділяємо всіх користувачів із сукупності в класичному дизайні експерименту, не враховуючи відмінностей між нашими користувачами. Таким чином, ми розглядаємо вибірку з наступним очікуваним значенням і дисперсією.


Іншим способом є випадковий розподіл всередині кожної страти відповідно до ваги страти в загальній сукупності.

У цьому випадку очікуване значення та дисперсія такі.


Очікуване значення таке ж, як і в першому виборі. Однак дисперсія менша, що гарантує вищу чутливість метрики.

Тепер давайте розглянемо метод Неймана . Вони пропонують розподіляти користувачів випадковим чином усередині кожної страти з певною вагою.

Отже, очікуване значення та дисперсія в цьому випадку дорівнюють наступному.

Очікуване значення асимптотично дорівнює очікуваному значенню в першому випадку. Однак розбіжність значно менша.

Емпіричне тестування

Ми теоретично довели ефективність цього методу. Давайте змоделюємо зразки та емпірично перевіримо метод стратифікації.

Розглянемо три випадки:

  • усі страти з рівними середніми значеннями та дисперсіями,
  • усі страти з різними середніми та рівними дисперсіями,
  • усі страти з однаковими середніми та різними дисперсіями.

Ми застосуємо всі три методи в усіх випадках і побудуємо гістограму та коробковий графік для їх порівняння.

Підготовка коду

По-перше, давайте створимо клас на Python, який імітує нашу генеральну сукупність, що складається з трьох стратегій.

 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]


Потім додамо функції для трьох методів вибірки, описаних у теоретичній частині.

 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


Крім того, для емпіричної частини нам завжди потрібна функція для моделювання процесу експерименту.

 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


Результати моделювання

Якщо ми подивимося на генеральну сукупність, де всі наші страти мають однакові значення та дисперсії, очікується, що результати всіх трьох методів будуть більш-менш однаковими.

Різні середні та однакові дисперсії дали більш захоплюючі результати. Використання стратифікації значно зменшує дисперсію.

У випадках з однаковими середніми та різними дисперсіями ми бачимо зменшення дисперсії в методі Неймана.

Висновок

Тепер ви можете застосувати метод стратифікації, щоб зменшити дисперсію показників і посилити експеримент, якщо згрупувати свою аудиторію та технічно розділити її випадковим чином у кожному кластері з певними вагами!