<jupyter_start><jupyter_text>Стратификация  Необходимые модули<jupyter_code>import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from math import ceil
from scipy.optimize import minimize
from scipy.optimize import basinhopping
from sklearn.mixture import BayesianGaussianMixture<jupyter_output><empty_output><jupyter_text>Вспомогательные методы В данном методе формируется генеральная выборка. Пропорция может быть на только для трех компонент, но и, вообще говоря, для любого количества. Мат. ожидание и стандартное отклонение выбираются из равномерного распределения.<jupyter_code>def generate_sample(proportion, size, mu_differs, sigma_differs):
    sub_sample_sizes = np.array(list(map(lambda x: int(x * (size / sum(proportion))), proportion)))
    if mu_differs:
        mu_array = np.array([np.random.randint(-100, 100) for i in proportion])
    else:
        mu_array = np.array([np.random.randint(-100, 100)] * len(proportion))
    if sigma_differs:
        sigma_array = np.array([np.random.randint(100) for i in proportion])
    else:
        sigma_array = np.array([np.random.randint(100)] * len(proportion))
    result = np.hstack([np.random.normal(mu_array[i], sigma_array[i], size=sub_sample_sizes[i]) for i in range(len(proportion))])
    np.random.shuffle(result)
    return result<jupyter_output><empty_output><jupyter_text>Здесь мы просто генерируем необходимое количество равномерно распределенных индексов, по которым извлекаем элементы из генеральной совокупности.<jupyter_code>def simpleSalpmling(generalSample, subSampleSize):
    return np.array([generalSample[i] for i in list(np.random.randint(0, len(generalSample), subSampleSize))])<jupyter_output><empty_output><jupyter_text>Здесь функция построена так, что сначала определяются сколько элементов выборки приходится на долю в пропорции, затем определяется, сколько элементов необходимо извлечь из из выборки для каждой компоненты, чтобы в получившейся выборке сохранилась пропорция. Данная функция затем используется в процессе оптимизации с тем, чтобы определить, какая пропорция обеспечивает максимальную похожесть выборки на генеральную совокупность (минимизируется сумма модулей компонент гистограмм для генеральной совокупности и выборки).<jupyter_code>def proportional_sampling(proportion, sub_sample_size, general_sample):
    proportion = list(map(ceil, proportion))
    proportion = list(map(int, proportion))
    proportion = list(map(lambda x: x if x > 0 else 1, proportion))
    step = int(len(general_sample) / sum(proportion))
    count_pro_portion = int(sub_sample_size / sum(proportion))
    proportion = np.array(proportion)
    result = np.hstack([
        list(
            map(
                lambda x: general_sample[x],
                np.random.randint(
                    min(step * sum(proportion[:i]), step * sum(proportion[:i + 1])),
                    max(step * sum(proportion[:i]), step * sum(proportion[:i + 1])),
                    count_pro_portion * proportion[i]
                )
            )
        ) for i in range(len(proportion))])
    np.random.shuffle(result)
    return result
def minimization_function(proportion, general_sample):
    hist = np.histogram(general_sample, 50, density=True)[0]
    sub_sample = proportional_sampling(proportion, int(len(general_sample) / 10), general_sample)
    hist1 = np.histogram(sub_sample, 50, density=True)[0]
    return sum(np.abs(hist - hist1))
def minimize_result(initial_proportion, sample):
    res = minimize(
        minimization_function,
        initial_proportion,
        args=(sample),
        method='SLSQP',
        options={'eps': 1.0, 'ftol': 1e-8, 'disp': False},
        bounds=[(1, 10) for i in range(len(initial_proportion))]
    )
    #print(list(map(int, list(map(ceil, res.x)))))
    return list(map(int, list(map(ceil, res.x))))
def minimize_result1(initial_proportion, sample):
    bounds = [(1, 10) for i in initial_proportion]
    minimizer_kwargs = {"method": "SLSQP", "args": sample, "bounds": bounds}
    res = basinhopping(minimization_function, initial_proportion, minimizer_kwargs=minimizer_kwargs, niter=20)
    x = list(map(ceil, res.x))
    x = list(map(int, x))
    x = list(map(lambda x: x if x > 0 else 1, x))
    #print(x)
    return x<jupyter_output><empty_output><jupyter_text>Здесь используется байесовская оптимизация с тем, чтобы получить апостериорную оценку распределения и выделить компоненты смеси.<jupyter_code>def optimalSampling(generalSample, subSampleSize):
    mixture  = BayesianGaussianMixture(n_components=4, max_iter=int(1e10))
    mixture.fit(generalSample.reshape(-1, 1))
    #print(mixture.get_params())
    sub_sample = mixture.sample(subSampleSize)[0]
    return sub_sample<jupyter_output><empty_output><jupyter_text>Генерация выборки<jupyter_code>proportion = (5, 2, 1, 7)
sample = generate_sample(proportion, 1000 * sum(proportion), False, False)
sub_sample = simpleSalpmling(sample, 50 * sum(proportion))
print(sample.mean(), sample.std())
print(sub_sample.mean(), sub_sample.std())
print(sample.mean() - sub_sample.mean(), sample.std() - sub_sample.std())
plt.hist(sample, 50, normed=True)
plt.hist(sub_sample, 50, normed=True)
plt.show()
sub_sample = proportional_sampling(minimize_result([1, 1, 1, 1], sample), 50 * sum(proportion), sample)
print(sample.mean(), sample.std())
print(sub_sample.mean(), sub_sample.std())
print(sample.mean() - sub_sample.mean(), sample.std() - sub_sample.std())
plt.hist(sample, 50, normed=True)
plt.hist(sub_sample, 50, normed=True)
plt.show()
sub_sample = optimalSampling(sample, 50 * sum(proportion))
print(sample.mean(), sample.std())
print(sub_sample.mean(), sub_sample.std())
print(sample.mean() - sub_sample.mean(), sample.std() - sub_sample.std())
plt.hist(sample, 50, normed=True)
plt.hist(sub_sample, 50, normed=True)
plt.show()
%%time
proportion = (5, 2, 1, 7)
n = 50
%%time
samples = [generate_sample(proportion, 1000 * sum(proportion), False, False) for i in range(n)]
%%time
simple_sub_samples = [simpleSalpmling(samples[i], 50 * sum(proportion)) for i in range(n)]
%%time
proportional_sub_samples = [proportional_sampling(minimize_result([1, 1, 1, 1], samples[i]), 50 * sum(proportion), samples[i]) for i in range(n)]
%%time
optimal_sub_samples = [optimalSampling(samples[i], 50 * sum(proportion)) for i in range(n)]
plt.hist(list(map(np.mean, samples)), 50, normed=True)
plt.show()
plt.hist(list(map(np.mean, simple_sub_samples)), 50, normed=True)
plt.show()
plt.hist(list(map(np.mean, proportional_sub_samples)), 50, normed=True)
plt.show()
plt.hist(list(map(np.mean, optimal_sub_samples)), 50, normed=True)
plt.show()
hist_samples = np.histogram(list(map(np.mean, samples)), 50, density=True)[0]
hist_simple_sub_samples = np.histogram(list(map(np.mean, simple_sub_samples)), 50, density=True)[0]
hist_proportional_sub_samples = np.histogram(list(map(np.mean, proportional_sub_samples)), 50, density=True)[0]
hist_optimal_sub_samples = np.histogram(list(map(np.mean, optimal_sub_samples)), 50, density=True)[0]
print (sum(np.abs(hist_samples - hist_simple_sub_samples)))
print (sum(np.abs(hist_samples - hist_proportional_sub_samples)))
print (sum(np.abs(hist_samples - hist_optimal_sub_samples)))<jupyter_output>0.171239185074
0.171168218605
0.143214348987
{'fraction_non_alphanumeric': 0.12725519900840104, 'fraction_numerical': 0.022586420603222697, 'mean_word_length': 5.420866489832007, 'pattern_counts': {'":': 3, '<': 24, '<?xml version=': 0, '>': 26, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '365064', 'license': 'Unlicense', 'n_tokens_mistral': 2725, 'n_tokens_neox': 2612, 'n_words': 539, 'path': 'Second_Task.ipynb', 'repo_name': 'IooHooI/BASIC-STATISTICS', 'size': '7261'}