Как да не бъдете подведени от случайността, когато избирате най-добрия модел

Свикнали сме да виждаме предизвикателства в науката за данните в Kaggle, където вариация от 0,1% в ROC резултата може да направи разликата между спечелването на 100 000 $ или нищо.

Вземете за пример предизвикателството Data Science Bowl 2017. Наградите бяха 500 000 $ за 1-во място, 200 000 за 2-ро място, 100 000 за 3-то място и т.н. Избраният показател за оценка беше логаритмична загуба. Това беше крайната класация:

Каква според вас е разликата между модела на 1-во място и модела на 2-ро място?

Ако отговорът ви е: „Разликата е, че първият модел е по-добър от втория модел, защото има по-малка лог-загуба“, тогава вероятно бързате. Всъщност,

Как можем да сме сигурни, че по-добра метрика в тестовия набор означава по-добър модел, а не просто по-щастлив модел?

Направих този пример за Kaggle, но същото разсъждение важи за всяка ситуация от реалния живот, в която трябва да изберем модел пред други.

Знаейки коя роля се играе случайно при избора на модел е основно умение за специалиста по данни. В тази статия ще видим как да определим количествено произволността, включена в процеса на избор на най-добрия модел.

Кой всъщност е „най-добрият модел“?

На първо място, имаме нужда от недвусмислена дефиниция на това, което имаме предвид, като казваме „най-добрият модел“.

Представете си, че имаме два модела, A и B, и искаме да изберем най-добрия. Всички сме съгласни, че най-добрият модел е моделът, който се представя най-добре при невидяни данни.

По този начин ние събираме някои тестови данни (неизползвани по време на обучение) и оценяваме нашите модели върху тях. Да кажем, че модел A има 86% ROC резултат, а модел B 85%. Това означава ли, че модел A е по-добър от B? Засега да.

Но си представете, че след известно време сте събрали повече данни и сте ги добавили към предишния набор от тестове. Сега модел A все още е 86%, но модел B се е увеличил до 87%. В този момент Б е по-добро от А. Как е възможно?

Изглежда очевидно, че единствената недвусмислена дефиниция е следната:

За дадена задача най-добрият модел е моделът, който се представя най-добре за всички възможни невидими данни.

Важната част от това определение е „всички възможни“. Наистина винаги имаме достъп до ограничени данни, така че нашият набор от тестови данни е само малка част от всички възможни невидими данни. Това е все едно да кажем, че никога няма да разберем кой е най-добрият модел!

За да се справим с този проблем, се нуждаем от нова концепция.

Представяне на Вселената

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

Истинското представяне на един модел е неговото представяне във вселената. В този случай истинският ROC резултат на модела е 80,4%. Ние обаче никога не можем да наблюдаваме Вселената и, като следствие, никога не можем да наблюдаваме истинския ROC на модела.

Всичко, което можем да наблюдаваме, е ROC резултатът, изчислен върху тестовия комплект. Понякога ще бъде по-висок (81,6%), понякога ще бъде по-малък (79,9% и 78,5%), но няма начин да знаем колко далеч е истинският ROC резултат от наблюдавания ROC резултат.

Всичко, което можем да направим, е да се опитаме да преценим колко произволност е включена в процеса. За да направим това, ще трябва да симулираме вселената и да извадим много произволни набори от тестови данни от нея. По този начин можем да определим количествено дисперсията на наблюдаваните резултати.

Как да симулираме Вселената?

Нашата цел е да получим набор от наблюдения с даден ROC резултат. Оказва се, че има доста прост начин да направите това.

Първо, трябва да зададем желания брой индивиди във вселената (обикновено голям брой). След това трябва да зададем разпространението, т.е. процента на положителните (можем да го оставим на 50%, което е по подразбиране). Третата стъпка е изборът на ROC резултат, който искаме да бъде във вселената.

И накрая, можем да изчислим прогнозираната вероятност за всеки индивид във Вселената: негативите трябва да са равномерно разпределени между 0 и 1, докато положителните трябва да са равномерно разпределени между α и 1.

Където α може да се получи от ROC чрез следната формула:

Когато ROC е 50%, α е 0, което означава, че разпределението на негативите и позитивите е еднакво. Обратно, когато ROC е 100%, α е 1, което означава, че всички позитиви са концентрирани върху 1: няма припокриване между негативи и позитиви.

В Python това може да се преведе в следната функция:

def get_y_proba(roc, n=100000, prevalence=.5):
  '''Get two arrays, y and proba, for a given roc (greater than .5)'''
  n_ones = int(round(n * prevalence))
  n_zeros = n - n_ones
  y = np.array([0] * n_zeros + [1] * n_ones)
  alpha = (roc - .5) * 2
  proba_zeros = np.linspace(0, 1, n_zeros)
  proba_ones = np.linspace(alpha, 1, n_ones)
  proba = np.concatenate([proba_zeros, proba_ones])
  return y, proba

Получаване на нашата мярка за несигурност

Сега, когато имаме начин да създадем синтетична вселена, нека да получим нашата вселена със следната команда:

y_universe, proba_universe = get_y_proba(roc=.8, n=100000, prevalence=.5)

И така, нашата вселена е направена от 100 000 наблюдения, половината от които са положителни, и ROC резултат от 80%.

Сега нека симулираме извличането на различни тестови набори. Ще извлечем 5000 различни набора от тестове, всеки от които се състои от 1000 наблюдения, идващи от Вселената. Това е съответният код:

rocs_sample = []
for i in range(5_000):
  index = np.random.choice(range(len(y_universe)), 1_000, replace=True)
  y_sample, proba_sample = y[index], proba[index]
  roc_sample = roc_auc_score(y_sample, proba_sample)
  rocs_sample.append(roc_sample)

Това е разпределението на наблюдаваните ROC резултати:

Както можете да видите, резултатите са доста разнообразни, вариращи от по-малко от 76% до повече от 84%.

В нормалните приложения въпросът, на който бихме искали да отговорим, е следният. Имам два модела, единият има ROC резултат 78%, а другият 82%. Колко вероятно е те да имат еднакъв основен ROC и тази разлика да е просто резултат от случайност?

За да добием представа, можем да изчислим разстоянието между всяка двойка наблюдавани ROC резултати от нашата симулация. Scikit-learn има функция pairwise_distances, която позволява това.

import numpy as np
from sklearn.metrics import pairwise_distances

dist = pairwise_distances(np.array(rocs_sample).reshape(-1,1))
dist = dist[np.triu_indices(len(rocs_sample), k=1)]

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

95-ият персентил (маркиран с пунктирана линия) е около 4%. Това означава, че разликата между два модела (които имат еднаква производителност) е по-голяма от 4% само в пет процента от случаите.

Така, използвайки статистически жаргон, бихме казали, че разлика по-малка от 4% не е значима! Това е доста интересно, защото обикновено ни карат да мислим, че 82% ROC модел е много по-добър от 78% ROC модел.

За да получа друга визуализация на тази концепция, симулирах три различни вселени, една с ROC резултат от 75%, друга от 80% и последната от 81%. Това са разпределенията на техните наблюдавани ROC резултати.

От този сюжет е очевидно, че доста често най-добрият модел няма да спечели! Само си представете сравняване на десетки модели, всеки с различен истински ROC резултат.

Малко вероятно е наистина да изберете най-добрия модел. Най-вероятно ще изберете най-щастливия.

Мога ли да направя нещо по въпроса?

Значи ми казвате, че няма начин да съм 100% сигурен, че един модел е по-добър от друг? Това звучи като кошмар. Разбира се: няма такова нещо като 100% сигурност в науката за данните. Не се отчайвайте обаче.

Разумно е да се очаква, че степента на несигурност при избора на най-добрия модел зависи както от характеристиките на Вселената, така и от характеристиките на тестовия набор, извлечен от Вселената. По-специално, има три параметъра, които управляват несигурността:

  • True ROC: ROC резултат, изчислен във вселената.
  • Размерност на извадката: брой наблюдения в тестовия набор.
  • Разпространение на пробата: процент на положителните резултати в тестовия набор.

За да видя как тези елементи влияят върху несигурността, симулирах какво се случва, като опитах различни стойности за всеки от тях:

  • Истински ROC: 70%, 80% и 90%.
  • Размерност на извадката: 1000, 5000 и 10 000 наблюдения.
  • Разпространение на извадката: 1%, 5% и 20%.

Тъй като изпробваме три стойности за три параметъра, това означава 27 възможни комбинации.

За всяка комбинация симулирах вселена, след това взех проби от 1000 различни набора от тестове и измерих съответните ROC резултати. След това изчислих матрицата на разстоянието на 1000 ROC резултата. И накрая, взех 95-ия процентил на разстоянията (наричан „d“ отсега нататък). Както казах по-горе, това е мярка за несигурността при избора на модел.

Например, това са първите 5 изпитания от 27-те.

Ние измерваме несигурността с 95-ия процентил. Колкото по-високо е това число, толкова по-голяма е несигурността при сравняването на ROC кривите.

Тъй като искаме да знаем как несигурността зависи от 3-те параметъра, интересно е да се измери частичната корелация между всеки параметър и „d“. Това е резултатът:

Колоната, наречена „r“, показва частичната корелация между всеки параметър и несигурността. Всички коефициенти на корелация са отрицателни, което показва, че увеличаването на някой от тези три намалява несигурността. В частност,

  • Истинска ROC. По-висок ROC резултат във вселената означава по-малко несигурност. Това има смисъл, защото по-висок ROC означава по-малка степен на несигурност по дефиниция.
  • Примерно измерение. Увеличаването на размера на пробата намалява несигурността. Това е доста очевидно и се случва през цялото време в статистиката.
  • Разпространение на извадката. Увеличаването на разпространението намалява несигурността. По-малкото разпространение означава по-малко положителни резултати. По-малко положителни резултати означават, че произволността има по-голяма тежест при вземането на проби от тях. Оттук и по-голямата несигурност.

От любопитство, нека също визуализираме разпределенията на наблюдаваните ROC резултати при промяна на размерите на извадката и разпространението на извадката, за фиксиран истински ROC (80% в този случай).

Мисля, че това изображение говори само за себе си. Вземете горния ляв график. Както размерът на извадката, така и разпространението са много малки: имаме 1000 наблюдения и 1% положителни резултати, което означава 10 положителни и 990 отрицателни. В този случай несигурността е много висока и полученото разпределение на ROC резултатите е почти равномерно, от 75% до 85%. Освен това 95-ият персентил на разстоянието между ROC резултатите е 10%, което означава, че няма значителна разлика между наблюдавана ROC от 75% и наблюдавана ROC от 85%.

Въпреки това, тъй като постепенно увеличаваме размерите на извадката и/или разпространението, ситуацията се подобрява и разпределението на наблюдавания ROC резултат става все повече и повече концентрирано около истинската стойност (80% в този случай). Например, с 10 000 наблюдения и 20% от разпространението, 95-ият персентил става много по-разумните 1,2%.

Това полезно ли е за мен?

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

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

Можете да намерите целия код на Python, използван в тази статия, в моята страница в Github.

Ако искате да прочетете задълбочена дискусия по тази тема, по-скоро от гледна точка на тестване на хипотези (а не от гледна точка на симулация), можете да прочетете тази публикация в блога от Lauren Oakden Rayner: „Състезанията с AI не създават полезни модели

Благодарим ви, че прочетохте! Надявам се, че тази статия ви е харесала. Ако желаете, добавете ме в Linkedin!