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

Веднъж предоставени проби, които могат да бъдат подредени с различни техники, като „извадка от Bootstrap“, общата цел е да се направят изводи по реални параметри, принадлежащи на оригиналните популации, чрез изчисляване на така наречените статистики или оценители от нашата извадка.

Нуждаем се обаче от някакъв вид „застраховка“, че нашите оценки са близки до реалността на фактите. Ето защо използваме тестове за хипотези.

В тази статия ще дам практически пример с 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 (което означава, че не отхвърляме нулата, когато е невярна). За двойна проверка, нека изчислим 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 г.