paint-brush
Използване на метода на стратификация за анализ на експериментаот@nataliaogneva
33,155 показания
33,155 показания

Използване на метода на стратификация за анализ на експеримента

от 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


Резултати от симулацията

Ако погледнем общата съвкупност, където всички наши страти имат еднакви стойности и вариации, резултатите и от трите метода се очаква да бъдат повече или по-малко еднакви.

Различни средни стойности и равни дисперсии дават по-вълнуващи резултати. Използването на стратификация драстично намалява дисперсията.

В случаи с еднакви средни стойности и различни дисперсии виждаме намаляване на дисперсията в метода на Нейман.

Заключение

Сега можете да приложите метода на стратификация, за да намалите дисперсията на показателите и да засилите експеримента, ако групирате аудиторията си и технически я разделите на случаен принцип във всеки клъстер със специфични тегла!