Головна думка теми: модель дає впевненість, рішення ухвалюєш ти. Усі три рівні крутяться навколо неї.
рівень 1Рівень 1 — База
Візьми свої дані замість студентів із практики. Підійде будь-який набір з sklearn.datasets
з бінарною міткою — наприклад, load_breast_cancer() — або власна вигадана задача,
згенерована np.random.default_rng.
- Навчи
LogisticRegressionна одній числовій ознаці. - Побудуй графік: по осі x — ознака, по осі y — прогнозована ймовірність. Познач вертикальною лінією межу рішення $x^* = -\beta_0/\beta_1$.
- Порахуй precision і recall при порогах 0.3, 0.5 і 0.7.
Зроблено, якщо: є таблиця з трьох рядків (поріг, precision, recall), і ти написав(ла) одним реченням, у який бік рухається кожна метрика зі зростанням порогу і чому саме так.
рівень 2Рівень 2 — Плюс
Візьми незбалансовану задачу: зроби так, щоб позитивний клас становив 3–5%
(наприклад, make_classification(..., weights=[0.96, 0.04])).
- Навчи модель і поміряй accuracy при порозі 0.5.
- Поміряй accuracy тривіального класифікатора «завжди 0».
- Побудуй криву precision-recall і знайди найбільший поріг, при якому recall ≥ 0.80.
- Порівняй два способи впоратися з дисбалансом: зсув порогу та
class_weight='balanced'.
Зроблено, якщо: ти показав(ла) числом, що accuracy моделі майже не відрізняється від accuracy «завжди 0», назвав(ла) знайдений поріг і recall/precision у ньому, і зробив(ла) висновок, який із двох способів дав кращий precision при тому самому recall.
рівень 3Рівень 3 — Виклик
Реалізуй мультиноміальну (softmax) регресію з нуля на NumPy для трьох класів.
- Дані:
sklearn.datasets.load_iris(), дві ознаки на твій вибір (щоб можна було намалювати). - Softmax: $P(y=k\mid x) = e^{z_k} / \sum_j e^{z_j}$. Рахуй його стійко: відніми від усіх
логітів їхній максимум перед експонентою, інакше
np.expпереповниться. - Втрата — категорійна крос-ентропія $-\sum_k y_k \ln p_k$. Градієнт має ту саму форму, що й у бінарному випадку: $X^T(P - Y)$, де $Y$ — мітки в one-hot вигляді.
- Навчи градієнтним спуском і намалюй межі рішення на площині ознак.
Зроблено, якщо:
assert np.allclose(наші_ймовірності, sklearn_модель.predict_proba(X), atol=1e-3)
проходить для LogisticRegression(penalty=None, max_iter=10000), і на графіку видно
три області, розділені прямими лініями.
Підказки
- Рівень 1: якщо межа рішення вийшла за межі даних — це не помилка коду. Подивись на знак $\beta_1$ і на те, чи взагалі ознака розділяє класи.
- Рівень 2:
class_weight='balanced'не рухає поріг — він змінює саму функцію втрат, роблячи помилку на рідкому класі дорожчою. Тому й межа зміщується всередині моделі. - Рівень 3: при трьох класах softmax має одну «зайву ступінь свободи» — додавши однакове число до всіх логітів, ти нічого не зміниш. Тому коефіцієнти твої й бібліотечні можуть відрізнятися на константу, а ймовірності — ні. Порівнюй саме ймовірності.
- Скрізь, де щось не сходиться зі
sklearn: перша підозра — увімкнена за замовчуванням L2-регуляризація (penalty='l2',C=1).