Усі три рівні незалежні — можна робити будь-який. Здавати одним зошитом, у якому кожна відповідь супроводжується числом або графіком, а не лише словами.
рівень 1Рівень 1 — База
Повтори головний сюжет лекції на своїх даних: покажи, що апріорна ймовірність класу вирішує не менше, ніж якість ознаки.
Візьми будь-який текстовий датасет із sklearn.datasets — підійде
fetch_20newsgroups(subset='train', categories=[...]) на двох категоріях. Перетвори
тексти на лічильники слів через CountVectorizer(max_features=2000) і навчи
MultinomialNB().
Далі зроби класи нерівними штучно: залиш у навчальній вибірці лише 10% об'єктів
одного з класів (rng = np.random.default_rng(0), вибирай індекси без повернення)
і навчи модель ще раз на тих самих ознаках.
Зроблено, якщо:
- у таблиці зведено precision і recall рідкісного класу для обох варіантів навчання;
- виписано np.exp(модель.class_log_prior_) для обох варіантів — має бути видно, що
апріорні ймовірності змінились приблизно так, як змінились частки класів;
- одним реченням пояснено, чому саме precision рідкісного класу просів, і як це
пов'язано з розділом 3 лекції.
рівень 2Рівень 2 — Плюс
Виміряй, скільки коштує наївність, коли ознаки навмисно залежні.
Візьми числові дані з розділу 8 практики (відносна_ціна, вік_акаунта) і додай до
матриці ознак копії колонки відносна_ціна — по 0, 1, 3, 7 і 15 копій.
Копія не несе жодної нової інформації, тож ідеальна модель мала б її просто
проігнорувати. Щоразу міряй на тесті:
- точність (
accuracy); - середню ймовірність, яку модель приписала правильному класу
(
predict_probaпо рядках, вибираючи стовпчик за справжньою міткою); log_lossізsklearn.metrics.
Поруч зроби те саме для LogisticRegression(max_iter=5000) на тих самих матрицях.
Зроблено, якщо:
- побудовано графік «кількість копій ознаки → log_loss» із двома лініями
(GaussianNB і логістична регресія), осі підписані;
- у таблиці зведено всі три числа для 0 і для 15 копій, для обох моделей;
- названо, у скільки разів зріс log_loss наївного Баєса від 0 до 15 копій і на скільки
при цьому впала його точність — і показано, що логістична регресія на тих самих
матрицях майже не змінилась;
- сформульовано пояснення: дубльована ознака входить у добуток кілька разів, тож модель
рахує одне свідчення багато разів і стає самовпевненою — а log_loss карає саме
за самовпевненість, тому псується швидше за точність.
рівень 3Рівень 3 — Виклик
Напиши BernoulliNB з нуля й з'ясуй, у чому саме він відрізняється від
мультиноміального на тих самих даних.
- Реалізуй клас із методами
навчити(X, y)іпередбачити_ймовірності(X), деX— матриця 0/1. Для кожного класуcі кожної ознакиjрахуйp[c, j] = (кількість об'єктів класу c з ознакою j + α) / (об'єктів класу c + 2α). Ключова відмінність від мультиноміального: відсутність ознаки теж є свідченням, тож у добуток входитьp[c, j]для наявних ознак і1 − p[c, j]для відсутніх. - Усі обчислення веди в логарифмах, підсумкові ймовірності отримуй через log-sum-exp.
- Перевір на архіві зі ста оголошень із практики.
Зроблено, якщо:
- проходить перевірка
assert np.allclose(твої_ймовірності, BernoulliNB(alpha=1).fit(X, y).predict_proba(X))
на всіх ста рядках архіву;
- окремою клітинкою виведено ймовірності MultinomialNB(alpha=1) і BernoulliNB(alpha=1)
для оголошення ["терміново", "передоплата"] і для оголошення
["терміново", "передоплата", "торг", "гарантія", "чек"], і пояснено, чому два
класифікатори дають різні числа на обох (підказка: подивись, що бернуллі робить із
п'ятьма словами, яких у тексті немає);
- названо, скільки чисел зберігає кожна з двох моделей на цьому архіві, і чому
бернуллі-варіант природніший для коротких оголошень.
Підказки
- Рівень 1.
class_log_prior_— це логарифми апріорних ймовірностей, які модель узяла просто з часток класів у навчальній вибірці. Якщо хочеш перевірити ефект окремо від усього іншого, передайMultinomialNB(class_prior=[...])вручну й подивись, як зміняться прогнози на тих самих навчених частотах. - Рівень 2. Копії колонки зручно робити через
np.hstack([X] + [X[:, [0]]] * скільки). Додавати їх треба до розбиття на train/test, інакше матриці будуть різної ширини. Порівнюй моделі на тому самому розбитті:random_state=0іstratifyобов'язкові. - Рівень 3. Формулу з відсутніми ознаками зручно записати одним виразом:
X * log(p) + (1 - X) * log(1 - p)— сума цього по колонках і є логарифм правдоподібності рядка. Жодного циклу по об'єктах не потрібно. - Якщо
predict_probaбібліотеки й твоє число розходяться в останніх знаках, звір спершуpredict_log_proba: там видно, чи проблема в самих логарифмах, чи вже в нормуванні.