# Домашнє завдання · Кластеризація k-means

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

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

---

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

Візьми зошит із практики й доведи його до кінця ще раз, змінивши **рівно одну річ** —
другу ознаку. Замість `рік` візьми `вік_акаунта` (у днях, і теж під логарифмом — розкид
там від 3 днів до кількох років).

1. Побудуй нові дві ознаки, промасштабуй їх `StandardScaler`.
2. Прожени `кластеризувати` для k від 2 до 6, по 20 випадкових стартів на кожне k.
3. Побудуй криву ліктя й криву силуету.
4. Обери k, розбий дані й **назви кожен сегмент словами** — так, щоб назву зрозуміла
   людина, яка не бачила коду.

**Зроблено, якщо:** є дві криві, є обране k з одним реченням «чому саме воно», і є таблиця
сегментів, у якій кожен рядок має назву на кшталт «дешеві оголошення від нових акаунтів»,
а не «кластер 2».

---

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

Перевір, наскільки твої кластери взагалі стійкі. Це найкорисніша звичка з усієї теми, і в
зошиті вона показана лише побіжно.

Візьми розбиття при **k = 3** на ознаках «ціна + рік» (те саме, що в практиці) і проведи
три перевірки:

1. **Викидання рядків.** Десять разів прибери випадкові 20 % оголошень, перекластеризуй
   решту й порахуй `adjusted_rand_score` з повним розбиттям на тих самих рядках.
   Запиши середнє й розмах.
2. **Зашумлення.** Додай до масштабованих ознак нормальний шум із σ = 0.1, потім σ = 0.3,
   перекластеризуй і порівняй з початковим розбиттям тим самим ARI.
3. **Викиди.** Прибери вісім найдорожчих оголошень (колекційні `Gamma X` і одруки з
   [теми 08](../08-pandas-eda/lecture.html)) і подивись, чи змінилися центри та розміри груп.

Потім дай відповідь на головне питання: **яка з трьох перевірок зруйнувала розбиття
найсильніше і чому саме вона?**

**Зроблено, якщо:** є три числа ARI (середнє по викиданню рядків, ARI при σ = 0.1 і при
σ = 0.3), є таблиця центрів до і після прибирання викидів, і є два-три речення про те, що
саме виявилось найкрихкішим.

---

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

Знайди дані, на яких k-means **дає очевидно неправильну відповідь**, і доведи це числом.

1. Згенеруй три набори точок, у кожному з яких людина бачить дві групи одразу:
   - дві витягнуті паралельні смуги,
   - коло всередині кільця,
   - щільна купка поруч із розсіяною хмарою.
   Кожен набір — 150–250 точок; справжню приналежність зберігай окремим масивом.
2. Прожени на кожному k-means при k = 2 (можна свій, можна `KMeans` — результат той самий).
3. Для кожного набору порахуй **частку точок на своїх місцях**: перебери обидва способи
   зіставити номери кластерів зі справжніми групами й візьми кращий. Порахуй ще й ARI.
4. Намалюй три картинки поряд: колір = те, що знайшов k-means.
5. Для кожного випадку напиши **одне речення про причину**, і причина має бути про
   геометрію, а не про «алгоритм поганий».

Далі — друга половина, і вона важливіша за першу. Візьми `sklearn.cluster.DBSCAN` та
`sklearn.cluster.AgglomerativeClustering` і прожени їх на тих самих трьох наборах.
Для DBSCAN доведеться підібрати `eps` і `min_samples`; для агломеративної спробуй
`linkage="ward"` і `linkage="single"`.

**Зроблено, якщо:**

1. є таблиця 3 набори × 4 методи (k-means, DBSCAN, ward, single) із часткою правильно
   згрупованих точок і ARI у кожній клітинці;
2. є картинки, на яких видно, хто де помилився;
3. є речення на кожен із трьох наборів: **чому** k-means там програв;
4. є одне речення про те, який метод виграв найчастіше — і чому це **не** означає, що ним
   треба користуватись завжди.

---

## Підказки

- **Не шукай «правильну» кількість кластерів.** Лікоть і силует не зобов'язані
  погоджуватись, і в лекції вони й не погодились. Твоє завдання — не вгадати число, а
  назвати діапазон і пояснити, чому обрав саме це k всередині нього.
- **Стійкість перевіряють через ARI, а не через збіг номерів.** Кластер 0 у другому
  запуску легко стає кластером 2 — номери довільні. `adjusted_rand_score` це враховує:
  він порівнює, які точки опинились разом, а не як їх назвали.
- **Другий рівень, шум:** додавай його вже до **масштабованих** ознак — тоді σ = 0.1
  означає «десята частина стандартного відхилення», і число можна порівнювати між ознаками.
- **Третій рівень, DBSCAN:** почни з `min_samples=5` і підбирай `eps` від малого до
  великого. Якщо все стало одним кластером — `eps` завеликий; якщо все стало шумом
  (мітка `-1`) — замалий. Точки-шум у підрахунку частки правильно згрупованих доведеться
  зарахувати як помилки, і це чесно: метод відмовився їх класифікувати.
- **Три вкладені кола:** для «кола всередині кільця» точки зручно генерувати в полярних
  координатах — випадковий кут і радіус із невеликим шумом, потім `x = r·cos(кут)`,
  `y = r·sin(кут)`.
