В своей предыдущей статье я говорил о статистических проверках гипотез. Они имеют решающее значение в статистике и науке о данных, поскольку нас всегда просят обобщить огромное количество данных, которые мы хотим проанализировать, на выборках.

После получения выборок, которые можно упорядочить с помощью различных методов, таких как выборка начальной загрузки, общая цель состоит в том, чтобы сделать выводы о реальных параметрах, принадлежащих исходным популяциям, путем вычисления так называемой статистики или оценок из нашей выборки.

Однако нам нужна какая-то «страховка», чтобы наши оценки были близки к реальности. Вот почему мы используем проверку гипотез.

В этой статье я собираюсь предоставить практический пример с Python со случайно сгенерированными данными, чтобы вы могли легко визуализировать все потенциальные результаты теста.

Итак, начнем с создания наших данных:

import numpy as np
mu, sigma = 3, 2 
s = np.random.normal(mu, sigma, 10000)
import matplotlib.pyplot as plt
count, bins, ignored = plt.hist(s, 30, density=True)
plt.plot(bins, 1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (bins - mu)**2 / (2 * sigma**2) ),linewidth=2, color='r')
plt.show()

Как видите, я вручную сгенерировал нормально распределенные данные со средним значением = 3 и стандартным отклонением = 2. Теперь идея состоит в том, чтобы извлечь выборку из этой совокупности и проверить, действительно ли она была извлечена из совокупности со средним значением = 3. Для этой цели, поскольку я хочу, чтобы визуализация была четкой, я создам другое ручное распределение, все еще нормальное, но с другим средним значением (представьте, что оно было взято из популяции).

import numpy as np
sample_mean, sample_sigma = 1.5, 2
sample = np.random.normal(sample_mean, sample_sigma, 200)

Поскольку я вручную создал подвыборку этой популяции со средним заведомо меньше 3 (фактически 1,5), наши гипотезы будут такими:

Во-первых, давайте посмотрим на распределение:

count, bins, ignored = plt.hist(s, 30, alpha=0.1, density=True)
sample_count, sample_bins, sample_ignored = plt.hist(sample, 30, alpha=0.1, color='r',density=True)
plt.plot(sample_bins,1/(sample_sigma * np.sqrt(2 * np.pi)) *np.exp( - (sample_bins - sample_mean)**2 / (2 * sample_sigma**2) ),linewidth=2, color='r')
plt.plot(bins,1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (bins - mu)**2 / (2 * sigma**2) ),linewidth=2, color='b')
plt.show()

Таким образом, красным цветом обозначено наше выборочное распределение, а синим - реальное распределение населения. В этом случае мы уже знаем ответ на нашу проблему: наша выборка не возникает из популяции с синим распределением, и это очевидно, поскольку я не извлекал эту выборку из нашей генеральной совокупности. Однако что, если вам не предоставлено реальное распределение населения? Нам нужно узнать о вероятности того, что среднее значение нашей выборки будет равно среднему значению для нашей генеральной совокупности.

Следовательно, давайте вычислим доверительный интервал нашей выборки. Напомним, что доверительный интервал x% выражает, что для данной генеральной совокупности и набора выборок из них в 95% этих выборок среднее значение выборки (или любой другой параметр, о котором вы спрашиваете) будет включен в этот интервал.

Мы можем легко вычислить интервал с уверенностью = 95% с помощью инструмента scipy:

import scipy
ci = scipy.stats.norm.interval(0.95, loc=1.5, scale=2)
count, bins, ignored = plt.hist(s, 30, alpha=0.1, density=True)
sample_count, sample_bins, sample_ignored = plt.hist(sample, 30, alpha=0.1, color='r',density=True)
plt.plot(sample_bins,1/(sample_sigma * np.sqrt(2 * np.pi)) *np.exp( - (sample_bins - sample_mean)**2 / (2 * sample_sigma**2) ),linewidth=2, color='r')
plt.plot(bins,1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (bins - mu)**2 / (2 * sigma**2) ),linewidth=2, color='b')
plt.axvline(ci[0],color='g')
plt.axvline(ci[1],color='g')
plt.show()

Теперь давайте узнаем о возможных результатах нашего теста:

count, bins, ignored = plt.hist(s, 30, alpha=0.1, density=True)
sample_count, sample_bins, sample_ignored = plt.hist(sample, 30, alpha=0.1, color='r',density=True)
plt.plot(sample_bins,1/(sample_sigma * np.sqrt(2 * np.pi)) *np.exp( - (sample_bins - sample_mean)**2 / (2 * sample_sigma**2) ),linewidth=2, color='r')
plt.plot(bins,1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (bins - mu)**2 / (2 * sigma**2) ),linewidth=2, color='b')
plt.axvline(ci[0],color='g')
plt.axvline(ci[1],color='g')
plt.fill_between(x=np.arange(-4,ci[0],0.01), 
                 y1= scipy.stats.norm.pdf(np.arange(-4,ci[0],0.01),loc=1.5,scale=2) ,
                 facecolor='red',
                 alpha=0.35)

plt.fill_between(x=np.arange(ci[1],7.5,0.01), 
                 y1= scipy.stats.norm.pdf(np.arange(ci[1],7.5,0.01),loc=1.5,scale=2) ,
                 facecolor='red',
                 alpha=0.5)

plt.fill_between(x=np.arange(ci[0],ci[1],0.01), 
                 y1= scipy.stats.norm.pdf(np.arange(ci[0],ci[1],0.01),loc=3, scale=2) ,
                 facecolor='blue',
                 alpha=0.5)

plt.text(x=0, y=0.18, s= "Null Hypothesis")
plt.text(x=6, y=0.05, s= "Alternative")
plt.text(x=-4, y=0.01, s= "Type 1 Error")
plt.text(x=6.2, y=0.01, s= "Type 1 Error")
plt.text(x=2, y=0.02, s= "Type 2 Error")

plt.show()

Как видите, пример среднего (1.5) включен в область ошибки типа 2 (это означает, что мы не отклоняем значение null, если оно ложно). Чтобы перепроверить, давайте вычислим p-значение, имея в виду, что наш уровень достоверности составляет 5% (следовательно, мы не отклоняем ноль, если p-значение больше 5%).

z_score=(sample_mean-mu)/sigma 
p_value = scipy.stats.norm.sf(abs(z_score)) 
print('P-value= {}'.format(p_value))
 
if p_value<0.05: 
     print('P-value<alpha: reject H0') 
else: 
     print('P-value>alpha: do not reject H0')

Как видите, наш тест подтвердил то, что показано на рисунке выше: мы можем сказать с 95% уверенностью, что наша выборка была извлечена из генеральной совокупности со средним значением = 1,5. Конечно, мы знаем, что это неправда, поскольку реальное население имеет среднее значение = 3. Итак, как мы можем справиться с этим несоответствием? Ответ в том, что мы не можем. Я имею в виду, что мы могли бы сократить наш доверительный интервал, но имейте в виду, что это может привести к ошибке 1-го типа (отклонение нуля, если оно истинно).

Итак, идея состоит в том, чтобы сбалансировать размер вашего доверительного интервала в зависимости от типа задачи, с которой вы сталкиваетесь. А именно, если отклонение нулевого значения, когда оно истинно, означало бы огромную потерю доходов, вы бы предпочли сохранить свой доверительный интервал достаточно большим, чтобы только действительно экстремальные значения приводили к отклонению вашего нулевого значения.

Первоначально опубликовано на http://datasciencechalktalk.com 2 сентября 2019 г.