# Домашнє завдання · Ієрархічна кластеризація та DBSCAN

> Лекція: [lecture.html](lecture.html) · Практика: [practice.ipynb](practice.ipynb) · Тест: [quiz.html](quiz.html)

Правильної відповіді тут по-старому немає, тому завдання перевіряють не метрику, а
**чи можеш ти пояснити, що саме знайшов метод і чому саме це**. У всіх трьох рівнях
працюй із дошкою оголошень із практики й не забувай масштабувати ознаки — обидва методи
цієї теми міряють відстані.

---

## 🟢 Рівень 1 — База

Прожени DBSCAN по дошці на **іншій парі ознак**: логарифм ціни й логарифм віку акаунта
(`вік_акаунта` у днях, від 3 до кількох тисяч — без логарифма розкид зʼїсть усе інше).
Обидві ознаки приведи до z-оцінок.

1. Побудуй графік відстані до 4-го сусіда, відсортований, і знайди на ньому коліно.
2. Візьми `eps` із коліна, `min_samples = 5` і запусти DBSCAN.
3. Випиши, скільки вийшло кластерів, скільки точок у шумі та яка частка шуму.
4. Подивись на шумові оголошення: яка в них ціна, який вік акаунта, скільки серед них
   позначено як `шахрайське`.

**Зроблено, якщо:** є графік k-ї відстані з позначеним коліном, є таблиця «кластерів /
шуму / частка шуму» щонайменше для трьох різних `eps` (нижче коліна, на коліні, вище) і
два речення про те, хто саме опинився в шумі — з числами, а не «підозрілі оголошення».

---

## 🟡 Рівень 2 — Плюс

Візьми випадкові **40 оголошень** із дошки (`np.random.default_rng(0)`) і побудуй для них
**чотири дендрограми** — `single`, `complete`, `average`, `ward` — через
`scipy.cluster.hierarchy.linkage` і `dendrogram`.

Для кожного звʼязку розріж дерево на три групи (`fcluster(..., 3, criterion="maxclust")`)
і запиши розміри груп та медіанну ціну кожної.

Питання, на які треба відповісти числами:

* у якого звʼязку найбільша група найбільша — і на скільки?
* на якій висоті відбувається останнє злиття в кожному з чотирьох дерев і чому ці висоти
  такі різні?
* чи знайшовся хоч один звʼязок, у якого всі три групи мають хоча б по пʼять оголошень?

**Зроблено, якщо:** є чотири дендрограми на одному малюнку, таблиця з розмірами й
медіанними цінами груп для кожного звʼязку і одне речення, яке пояснює ланцюжковий ефект
на цих конкретних числах (тобто називає, скільки оголошень зібрав велетень у `single`).

---

## 🔴 Рівень 3 — Виклик

Перевір на ділі обіцянку **HDBSCAN** — розширення, яке нібито знімає головну ваду DBSCAN,
бо не вимагає єдиного `eps` на весь простір.

1. Візьми три форми з практики (смуги, кільця, різна щільність).
2. Для **DBSCAN** пройди сітку: `eps` від 0.2 до 1.2 з кроком 0.05 при
   `min_samples = 5`, і для кожної форми запиши **найкращий** досягнутий
   `adjusted_rand_score`.
3. Для **HDBSCAN** (`from sklearn.cluster import HDBSCAN`, потрібен `scikit-learn` 1.3
   або новіший) перебери `min_cluster_size` у 5, 10, 15, 20 і так само запиши найкращий ARI
   та кількість шумових точок.
4. Склади підсумкову таблицю: форма × метод × найкращий ARI × скільки точок у шумі.

**Зроблено, якщо:** таблиця побудована й ти письмово відповів на два питання: (1) чи справді
HDBSCAN виграв на наборі з різною щільністю — і якщо ні, то на скільки програв; (2) чому
порівняння «найкращий ARI з сітки» — нечесне на користь DBSCAN, і як його треба було б
провести в реальній задачі, де правильних відповідей немає.

Друге питання важливіше за перше. Відповідь на нього — одне речення, але саме воно
відрізняє того, хто зрозумів тему, від того, хто просто прогнав код.

---

## Підказки

* Коліно на графіку k-ї відстані шукається очима, і це нормально. Якщо хочеться числа —
  подивись, при якій висоті кількість точок вище лінії приблизно збігається з тим, скільки
  дивних оголошень ти готовий назвати шумом.
* `scipy.cluster.hierarchy.dendrogram` малює дерево, а `fcluster` дає мітки. Це дві різні
  функції над тим самим результатом `linkage` — рахувати дерево двічі не треба.
* Якщо в рівні 3 HDBSCAN дає нуль кластерів і суцільний шум — це не помилка коду, а
  завеликий `min_cluster_size` для такого набору. Такий результат теж іде в таблицю.
