Към съдържанието
wannacode

Проверка на хипотеза

Накратко: Проверката на хипотеза пита дали разликата може да е случайност: нулевата хипотеза казва „няма разлика“, а p-стойността е колко често случайността дава поне такава разлика.

Проблем

„Петъкът наистина ли е по-силен?“

Управителят иска да сложи още един човек на опаковането в петък и да махне един в неделя. Преди това пита: петъкът наистина ли е по-силен, или така се е паднало тази година? Ето колко поръчки идват средно на ден, по ден от седмицата (0 е понеделник, 6 е неделя):

Pythonданни: таблиците на магазина

Броим всички поръчки, и отказаните: въпросът е колко пристигат, а и отказаната се приема и обработва. В петък идват средно 36,35 поръчки, а в неделя 24,62. Петъците в годината са 52 и неделите също. Всеки ден е малко различен: в един петък идват 22 поръчки, в друг 68. Дали 11,73 поръчки разлика е истинска, или е шум като в урока за извадките?

Идеята

Ако денят нямаше значение

Въпросът „петъкът по-силен ли е от неделята?“ е хипотеза. За да я провериш, започваш от скучното обяснение: денят няма значение и разликата е случайна. Това е нулевата хипотеза (null hypothesis).

Ако нулевата хипотеза е вярна, етикетите „петък“ и „неделя“ не значат нищо. Можеш да ги разбъркаш: слагаш 104-те дни на една купчина, разбъркваш ги и казваш, че първите 52 са „петъци“, а другите 52 „недели“. Разликата между двете половини е колко разлика дава самата случайност:

Pythonданни: таблиците на магазина

Истинската разлика е 11,73 поръчки. Три разбърквания дават 0,50, 1,23 и 1,46. np.concatenate слепва двата масива в един, а rng.permutation връща разбъркано копие.

Идеята

10 000 разбърквания и p-стойността

Три разбърквания са малко. Правиш 10 000 наведнъж: np.tile повтаря 104-те дни в 10 000 реда, а rng.permuted(..., axis=1) разбърква всеки ред поотделно. После една сметка дава разликата за всеки ред:

Pythonданни: таблиците на магазина

Най-голямата разлика от 10 000 разбърквания е 7,50 поръчки. Истинската е 11,73. Делът на разбъркванията с разлика поне толкова голяма е p-стойността (p-value): тук е 0, значи под 1 на 10 000. Ако денят нямаше значение, такава разлика почти никога нямаше да се получи. Заключението: петъкът наистина е по-силен.

Този начин се казва пермутационен тест (permutation test). np.abs е, защото въпросът е „има ли разлика“, без да казваш предварително в коя посока. Обичайният праг е 0,05: под него казваш, че разликата е статистически значима.

Пробвай

Понеделник и събота

1. Пермутационният тест за петък срещу неделя дава p = 0 от 10 000 разбърквания. Какво значи това?

Разликата между понеделник и събота е по-малка. Случайна ли е? Запиши в gap разликата в средния брой поръчки на ден (понеделник минус събота), в gaps разликите от 10 000 разбърквания, а в p p-стойността.

Pythonданни: таблиците на магазина

Идеята

Когато разлика няма

Неделята има по-малко поръчки. По-малки ли са и самите поръчки? Тук се сравняват 10 459 поръчки без отказаните, а не дни, затова таблица 2 000 × 10 459 с числа би заела около 170 MB. Цикълът с 2 000 разбърквания на маската е под секунда:

Pythonданни: таблиците на магазина

Неделните поръчки са 1 204, със средна 10,83 €, а другите са средно 10,60 €. Разликата е 0,23 € и p = 0,425: в 42,5% от разбъркванията разликата е поне толкова голяма. Това е обикновен шум.

Честният извод е „няма доказателство, че неделната поръчка е различна“. Не е „доказахме, че са равни“: малка разлика може да има, само че тези данни не могат да я покажат. В неделя хората поръчват по-рядко, а за по-малки поръчки доказателство няма.

Идеята

Какво p не казва

p-стойността отговаря на един тесен въпрос: колко изненадващи са данните, ако нулевата хипотеза е вярна. Тя не е две неща, с които често се бърка:

  • не е вероятността хипотезата да е вярна: p = 0,425 не значи „42,5% шанс да няма разлика“;
  • не е големината на разликата: много малко p значи „не е случайно“, а не „голяма разлика“.

Колко е голяма разликата казва самата разлика с интервал. С bootstrap от предишния урок, отделно за петъците и за неделите:

Pythonданни: таблиците на магазина

Петъкът има средно 11,73 поръчки повече, с 95% интервал от 9,00 до 14,56. Това е 1,48 пъти повече от неделята. С това число управителят решава колко хора да сложи, а p само казва, че не гони шум.

По-точно, за любопитните

Прагът 0,05 е договорка, не закон на природата. При p = 0,06 данните не са „почти доказателство“, а при p = 0,04 не са „сигурно вярно“. С много данни и нищожна разлика също дава малко p: при милион поръчки във всяка група и 10 цента разлика тестът ще е „значим“, но решение от това не следва. Затова винаги пиши и разликата, и интервала.

Идеята

Същото със scipy

scipy.stats има тестовете готови. ttest_ind (t-тест) сравнява средните на две групи по формула. permutation_test прави разбъркванията вместо теб, на парчета (batch), за да не свърши паметта:

Pythonданни: таблиците на магазина

За неделната поръчка t-тестът дава 0,426, permutation_test 0,419, а нашият цикъл 0,425. Отговорът е същият: няма доказателство. За петък срещу неделя t-тестът дава 1,04 × 10⁻¹²: нула за всички практически цели, като нашето 0 от 10 000.

По-точно, за любопитните

t-тестът приема, че средната на всяка група е разпределена почти нормално. При стотици поръчки в група това е вярно (централната гранична теорема). При малко данни с дълга опашка пермутационният тест е по-сигурен, защото не приема нищо за разпределението. permutation_test дава p малко по-различно от нашето: разбъркванията са други, а и брои самите данни като едно от тях, (брой + 1) / (разбърквания + 1).

Упражнение

Декември и петъкът

През декември се продават подаръчни карти. По-голяма ли е декемврийската поръчка от поръчките в другите месеци, или е случайно? Запиши в gap разликата в средната поръчка (декември минус другите месеци), а в p p-стойността. Можеш да ползваш пермутационен тест или stats.ttest_ind.

Pythonданни: таблиците на магазина

Петъчната поръчка е малко по-малка от поръчката в другите дни. Има ли доказателство за това? Направи пермутационен тест с 2 000 разбърквания (seed 42): gap е разликата в средната поръчка (петък минус другите дни), p е p-стойността, а evidence е дали p е под прага 0,05.

Pythonданни: таблиците на магазина

Тест

Провери се

1. Какво е нулевата хипотеза, когато сравняваш средната поръчка в неделя и в другите дни?
2. За неделната поръчка p = 0,425. Кое заключение е честно?
3. Защо p се смята с np.abs(gaps) >= abs(gap), а не с gaps >= gap?
4. p за декември е 5,1 × 10⁻²³, а за петък срещу неделя 1,0 × 10⁻¹². Значи ли това, че декември е по-голяма разлика?

Създаден от Иво Гергов като част от кампанията на Evo Tech за достъпно обучение по програмиране ·