Попередня тема закінчилась трьома картинками, на яких відповідь була очевидно неправильною. Дві довгі смуги, які k-means розрізав упоперек, — 58 % точок на своїх місцях. Коло всередині кільця — 60 %. Щільна купка поруч із розсіяною хмарою — 89 %. Людське око бачить правильну відповідь за півсекунди, а метод її не бачить узагалі.
Причина не в налаштуваннях. Вона в самій будові k-means: кожна точка йде до найближчого центра, тому межа між кластерами — завжди пряма, а кластер — завжди приблизно кругла грудка. Плюс друга незручність: кількість груп k доводиться назвати наперед, до того як ти щось про дані дізнався.
01 / Дві відповідіДві відповіді на одну невдачу
Обидві проблеми мають розвʼязок, і розвʼязки ці зовсім різні.
DBSCAN викидає з опису поняття центра. Замість «де середина групи» він питає «де точки стоять густо» — і нарощує кластер від сусіда до сусіда, куди б той не тягнувся. Смуга, кільце, підкова: якщо ланцюжок сусідів веде туди, кластер піде туди. Заразом він уміє те, чого k-means не вміє принципово, — сказати про окрему точку «це не кластер, це шум».
Ієрархічна кластеризація відповідає на другу проблему. Вона не видає одне розбиття. Вона будує дерево: спочатку кожен обʼєкт сам по собі, далі найближча пара зливається, далі наступна — аж поки все не стане однією групою. Кількість груп обираєш ти, але після побудови, дивлячись на дерево, а не наосліп до неї.
Працюємо на тих самих даних, що й у минулій темі. Наскрізний приклад — дошка оголошень про вживані телефони з теми 08: 1 100 оголошень із відомою ціною, дві ознаки — логарифм ціни й рік випуску, обидві приведені до z-оцінок. Плюс три синтетичні набори, на яких k-means провалився: витягнуті смуги, вкладені кільця, різна щільність. Ті самі точки, що й у темі 11, — щоб порівняння було чесним.
02 / ЩільністьКластер — це там, де густо
Уся ідея DBSCAN (density-based spatial clustering of applications with noise — кластеризація за щільністю з урахуванням шуму) тримається на одному спостереженні: усередині кластера точки стоять близько одна до одної, а між кластерами — порожньо. Не «кругло», не «навколо центра» — просто густо.
Щоб перетворити це на алгоритм, потрібні два числа, і задаєш їх ти.
eps(радіус околу) — наскільки близько має стояти точка, щоб вважатись сусідкою. Це відстань у тих самих одиницях, у яких лежать ознаки: у нас — у z-оцінках.min_samples(мінімум сусідів) — скільки точок має бути в цьому радіусі, щоб місце вважалось густим.
scikit-learn
min_samples рахує разом із самою точкою. Тобто
min_samples=3 означає «сама точка плюс щонайменше двоє сусідів», а не троє
сусідів. Помилка на одиницю тут не викине винятку — вона просто змістить межу
щільності.Далі кожна точка отримує одну з трьох ролей, і ці три слова — весь словник методу.
| роль | умова | що це означає |
|---|---|---|
| Ядерна (core) | у радіусі eps навколо неї — щонайменше min_samples точок | вона стоїть у густому місці й має право нарощувати кластер далі |
| Гранична (border) | сусідів замало, але вона сама лежить у радіусі якоїсь ядерної | вона в кластері, але з неї кластер далі не росте — це край |
| Шум (noise) | ні те, ні те | жодного кластера; алгоритм чесно каже «ця точка ні з ким» |
Візьмімо ті самі десять оголошень, на яких у минулій темі крутились ітерації k-means, і
роздамо їм ролі. Радіус eps = 1.2 (нагадаю: одиниця тут — одне стандартне
відхилення), min_samples = 3.
Схема 1 · Три ролі точки
Десять оголошень із розділу 3 попередньої теми. Навколо кожної точки — коло радіуса 1.2; підраховуємо, скільки точок у нього потрапило разом із нею самою.
| оголошення | z (ціна, рік) | точок у радіусі 1.2 | роль | кластер |
|---|---|---|---|---|
| A1 | −0.5, 1.1 | 3 | ядерна | 1 |
| A2 | −1.0, −1.1 | 2 | гранична | 2 |
| A3 | −2.5, −1.5 | 2 | гранична | 2 |
| A4 | 0.1, 1.5 | 4 | ядерна | 1 |
| A5 | 0.6, 1.5 | 6 | ядерна | 1 |
| A6 | 1.1, 0.7 | 4 | ядерна | 1 |
| A7 | 1.0, 1.5 | 5 | ядерна | 1 |
| A8 | 1.7, 1.5 | 4 | ядерна | 1 |
| A9 | 0.4, −1.5 | 1 | — | шум |
| A10 | −2.0, −0.6 | 3 | ядерна | 2 |
Gamma X Ultra 2017 року, у якого в темі 11 силует був 0.205 — k-means
мусив кудись його віднести, а DBSCAN просто каже «ні з ким».03 / АлгоритмЯк розростається кластер
Ролі роздано — далі алгоритм майже тривіальний. Він обходить точки одну за одною:
Прокрутімо це на наших десяти. Перша точка — A1, вона ядерна, відкриваємо кластер 1 і кладемо в чергу її сусідів A4 і A5. A4 ядерна — дописуємо її сусідів A1, A5, A7. A5 ядерна — дописує A6, A7, A8. Черга крутиться, поки не вичерпається, і кластер 1 виходить такий: A1, A4, A5, A6, A7, A8. Далі беремо A2 — не ядерна, позначаємо шумом тимчасово. A3 — те саме. A9 — теж не ядерна. Аж ось A10: ядерна, відкриваємо кластер 2, у чергу йдуть A2 і A3 — обидві не ядерні, тому нікого далі не тягнуть, і кластер 2 = A10, A2, A3. A9 так і лишається шумом.
Зверни увагу на два наслідки, які видно вже на десяти точках.
Перший: кластер може мати будь-яку форму. Він росте ланцюжком, від сусіда до сусіда, і жодного «центра» ніхто не рахує. Довга змія завтовшки в два кроки — законний кластер DBSCAN і неможливий кластер k-means.
Другий, дрібніший і неприємний: гранична точка може дістатись різним кластерам. Якби A2 лежала в колах двох різних ядерних точок із різних кластерів, її забрав би той, до кого черга дійшла першою, — тобто результат залежав би від порядку рядків у таблиці. Ядерних точок це не стосується: вони розподіляються однозначно. На практиці граничних точок мало, але якщо два запуски на перетасованих даних дали трохи різні мітки — причина зазвичай саме тут.
04 / ПараметриДва повзунки, дві катастрофи
Тепер найважливіше про DBSCAN: усе тримається на двох числах. Кількість
кластерів він і справді не питає — але eps і min_samples задають
її неявно, і крайні значення дають дві протилежні катастрофи.
Візьмімо ті самі дві витягнуті смуги, які завалили k-means, і додамо до них пʼятнадцять розкиданих поодиноких оголошень — щоб було на що подивитись у графі «шум». Разом 145 точок: 130 у двох смугах і 15 самих по собі.
Інтерактив 1 · eps і min_samples
Тягни обидва повзунки. Заповнені кружечки — ядерні точки, порожні — граничні, сірі хрестики — шум. Колір = кластер.
eps = 0.45 і min_samples = 5
DBSCAN знаходить рівно дві смуги й оголошує шумом рівно ті 15 точок, які ми туди й
підкинули. Зменш радіус до 0.15 при min_samples = 10 — і густих місць не
лишиться взагалі: усі 145 точок стануть шумом. Збільш до 1.30 — і смуги
зіллються в один суцільний кластер. Між цими краями є вузька смужка правильних
відповідей, і ширина цієї смужки — головна практична проблема методу.Обидва параметри тягнуть в один бік, але по-різному. eps вирішує, які
точки взагалі бачать одна одну; min_samples — наскільки густо має бути, щоб
місце вважалось кластером. Більший min_samples при тому самому радіусі
означає більше шуму й менше кластерів.
Типова порада для min_samples: бери щонайменше подвоєну кількість
ознак. У нас ознак дві, отже 4–5 — і саме тому в усіх прикладах цієї теми стоїть
пʼятірка. Порада груба, але вона хоч якось привʼязує число до даних.
05 / Вибір epsЗвідки брати eps
З eps складніше, бо це відстань, і «правильної» відстані ніхто не знає.
Стандартний прийом такий:
Сенс простий. Поки крива йде полого, ми рухаємось по точках, які сидять у густих місцях: до четвертого сусіда їм рукою подати. Коли крива задирається вгору — почались точки, у яких сусідів поблизу немає. Висота коліна і є та відстань, яка ще вважається «близько».
Схема 2 · Відстань до четвертого сусіда, відсортована
Ліворуч — наші 145 точок зі смугами. Праворуч — 1 100 справжніх оголошень із дошки.
eps з
коліна — 0.45–0.50 — і отримуємо ідеальний розподіл. На дошці оголошень крива
піднімається плавно: у половини оголошень четвертий сусід ближче ніж за 0.04, у
95 % — ближче ніж за 0.23, а далі відстань росте без жодного зламу. Це такий самий нечіткий критерій, як лікоть у
k-means: він окреслює розумний діапазон і не називає числа.06 / ШумШум — це відповідь
Тепер про властивість, якої немає в жодного методу з попередньої теми. DBSCAN
не зобовʼязаний віднести кожну точку до кластера. У
scikit-learn такі точки дістають мітку −1.
Звучить як вада — «алгоритм не впорався». Насправді це чесність. Коли k-means приписує дике оголошення до найближчого сегмента, він не додає знання, а ховає його: у групі «дешеві старі» тепер сидить телефон за 130 грн, який не схожий узагалі ні на що.
Подивись, що з цього виходить на справжніх даних. Запускаємо DBSCAN на всіх 1 100
оголошеннях дошки з eps = 0.3 і min_samples = 5. Результат
такий: 12 кластерів і 26 оголошень у шумі. І ось найцікавіше число всієї
теми: із цих 26 оголошень 25 позначені в таблиці як шахрайські. Алгоритм
цієї колонки не бачив.
| що вважаємо підозрілим | точність | повнота | F1 |
|---|---|---|---|
| шум DBSCAN (26 оголошень) | 0.962 | 0.180 | 0.303 |
| найдешевший кластер k-means (тема 11) | 0.206 | 0.525 | 0.296 |
| випадковий тик, 355 оголошень | 0.126 | 0.323 | 0.182 |
Читається це так. Шум DBSCAN майже не помиляється: з 26 піднятих тривог хибна одна. Але й ловить він мало — 25 шахраїв зі 139, тобто 18 %. Це ціни-приманки на кшталт 130 і 190 грн і завищені 45 320 та 83 500 грн: те, що стоїть на самому краю. Звичайного шахрая з ціною «трохи нижче ринку» жодна щільність не виловить, бо він лежить у гущі.
−1.eps менший за 0.43, вертикальних звʼязків між роками просто немає, і дошка
розпадається на горизонтальні смуги «всі оголошення 2019-го», «всі оголошення 2020-го».
Варто підняти eps до 0.5 — і 1 089 оголошень зливаються в один суцільний
кластер. Ніякої проміжної відповіді на цих даних немає: або смуги за роками, або одна
хмара. Це не поламаний DBSCAN — це чесна відповідь про дошку: щільнісно
відокремлених груп на ній немає.07 / ВадаОдна щільність на всіх
Головна вада DBSCAN схована в тому самому місці, що й перевага: eps у
нього один на весь простір. Метод припускає, що всі справжні кластери
мають приблизно однакову густину. Коли це не так, вибирати доводиться між двома
поразками. Обидва способи виразно кращі за жеребкування, але жоден не наближається до того, що дає розмітка: далі в курсі, коли дійдемо до моделей із учителем, та сама задача розвʼязується вчетверо точніше.
Це рівно той третій випадок із минулої теми — щільна купка й розсіяна хмара поруч, де
k-means дав 89 %. З параметрами, які ідеально спрацювали на смугах і кільцях
(eps = 0.6, min_samples = 5), DBSCAN дає на ньому
70 %: щільну купку знаходить бездоганно, а розсіяну хмару рве на
уламки й 30 її точок зі 150 оголошує шумом.
Можна підібрати eps під розсіяну хмару — 0.85. Тоді кластерів рівно два,
шуму лише 9 точок, а на своїх місцях 88 %. Це найкраще, що DBSCAN
взагалі може видати на цих даних, — і воно все одно трохи гірше за k-means. Причому
дійти до цього числа можна, тільки підглядаючи у правильну відповідь, якої в реальній
задачі немає.
eps взагалі. Він проганяє DBSCAN подумки
одразу для всіх радіусів, будує з цього дерево — так, те саме дерево, що й у другій
половині цієї теми, — і залишає ті кластери, які тримаються найдовше. Через це він
здатен знаходити групи різної щільності однією моделлю. Чарівної палички з нього
теж не виходить — на невеликих вибірках він помиляється не менше, і перевіряти його
доводиться так само руками. Ціна — складніша реалізація й окремий
пакет (hdbscan, а у свіжих версіях scikit-learn —
HDBSCAN). Ідею варто знати; коли eps ніяк не підбирається, це
перше, що слід спробувати.08 / ДеревоДерево замість розбиття
Другий метод теми починається з іншого питання. Не «де густо», а «що з чим схоже найбільше».
Такий напрямок — від окремих точок догори — зветься агломеративним (agglomerative, від «нагромаджувати»). Буває й зворотний, дивізивний: почати з однієї групи й ділити її. На практиці майже завжди беруть агломеративний, бо він простіший і передбачуваний.
Результат — не набір міток, а дендрограма (dendrogram, «деревна діаграма»). Читається вона так:
- кожен листок унизу — одне оголошення;
- кожна перемичка — злиття двох груп;
- висота перемички — відстань між групами в момент злиття. Низька перемичка означає «злилися схожі», висока — «злилися вимушено, бо більше нікого не лишилось».
А тепер найкорисніше. Проведи горизонтальну лінію на будь-якій висоті — і кожна вертикаль, яку вона перетне, стане окремою групою. Одне дерево, і скільки завгодно розбиттів. Кількість груп обирається після побудови, і обирається очима.
Інтерактив 2 · Дендрограма з рухомим зрізом
Двадцять вісім оголошень із дошки, злиття за середньою відстанню. Тягни повзунок — і дивись, скільки груп дає зріз і як вони лягають на площину.
09 / LinkageЧим міряти відстань між групами
В описі методу є одне слово, повз яке легко проскочити: «знаходимо дві найближчі групи». А що таке відстань між групами? Між двома точками вона очевидна. Між купкою з семи точок і купкою з дванадцяти — ні.
Відповідей чотири, вони звуться звʼязком (linkage), і вибір між ними міняє результат сильніше, ніж будь-що інше в методі.
| звʼязок | відстань між групами — це… | що з цього виходить |
|---|---|---|
| Одиночний (single) | відстань між двома найближчими точками груп | групи ростуть ланцюжками; знаходить змії й кільця, але злипається через один випадковий місток |
| Повний (complete) | відстань між двома найдальшими точками | групи виходять компактні, приблизно кулясті; довгу смугу розріже |
| Середній (average) | середнє з усіх попарних відстаней між групами | компроміс між першими двома, найчастіше — розумна поведінка за замовчуванням |
| Ворда (ward) | наскільки зросте сума квадратів відстаней усередині груп, якщо їх злити | мінімізує рівно те, що й інерція k-means; кулясті групи схожого розміру |
Найважливіший із цих чотирьох рядків — перший, і зветься це ланцюжковим ефектом. Одиночному звʼязку досить, щоб дві групи зʼєднала одна ланцюжкова доріжка з точок: далі він проковтне обидві. Це рівно те, що робить кластер DBSCAN довільної форми, — і рівно те, через що одиночний звʼязок розсипається на реальних даних. Ось наша дошка, ієрархічна кластеризація, три групи:
А тепер те саме на синтетиці, де правильна відповідь відома, — і виявиться, що переможець міняється місцями з невдахою.
Схема 3 · Чотири звʼязки, два набори даних
Угорі — дві витягнуті смуги, унизу — щільна купка й розсіяна хмара. Обидва рази ріжемо дерево на дві групи.
10 / ЦінаСкільки це коштує
За зручність «одразу вся ієрархія» доводиться платити, і платня росте квадратично. Щоб знайти найближчу пару, треба знати всі попарні відстані — а їх для n обʼєктів приблизно n²/2.
Тобто ієрархічна кластеризація — метод для тисяч рядків, не для мільйонів.
На сотнях тисяч вона просто не запуститься на звичайній машині. У DBSCAN та сама
квадратична біда в наївній реалізації, але її лагодить просторовий індекс:
scikit-learn шукає сусідів у радіусі через KD-дерево й на низьких
розмірностях працює приблизно за n·log n. Тому DBSCAN на мільйоні рядків — реально, а
дендрограма на мільйоні — ні.
І ще одна практична дрібниця, яку варто знати наперед. Ієрархічна кластеризація
не вміє приписати новий обʼєкт до вже готових груп: щоб додати один
рядок, треба перебудувати дерево. У k-means для цього досить порівняти відстані до
центрів. DBSCAN теж не має такого механізму — у scikit-learn у нього немає
навіть методу predict.
11 / РазомТри форми, три методи
Час скласти все докупи. Ось три набори даних, на яких провалився k-means, і три методи на кожному з них. Девʼять станів — перебери всі й подивись, хто де виграє.
Інтерактив 3 · Девʼять відповідей
Перемикай форму й метод. Числа під картинкою пораховані на тих самих точках, що й у попередній темі.
eps = 0.6 і min_samples = 5: одні
параметри на всі три набори, як і було б у житті, поки не почнеш підбирати.
Ієрархічна — звʼязок Ворда (він стоїть за замовчуванням у
AgglomerativeClustering), дерево розрізане на дві групи. У вердикті
для порівняння названо, що дав би на цьому ж наборі одиночний звʼязок.Підсумок у трьох рядках, і жоден із них не про перемогу:
- Витягнуті смуги й кільця. DBSCAN — 100 % і 100 %, одиночний звʼязок — те саме. k-means і Ворд — 56–66 %, тобто нічого. Форма довільна вимагає методу, який дивиться на сусідів, а не на центри.
- Різна щільність. Ворд 96 %, k-means 89 %, DBSCAN 70 %, одиночний звʼязок 65 %. Порядок перевернувся повністю: те, що вигравало щойно, тепер програє найгірше.
- Жодна конфігурація не виграє скрізь. Ані одна пара
(
eps,min_samples), ані один звʼязок. Це не недогляд авторів методів — це властивість задачі, у якій немає правильної відповіді.
12 / ВибірЩо обирати й що далі
Ось три методи в одній таблиці — не «який кращий», а що кожен припускає й на чому ламається.
| k-means | DBSCAN | Ієрархічна | |
|---|---|---|---|
| Що припускає про дані | кулясті групи схожого розміру | однакова щільність усередині всіх груп | нічого — усе вирішує обраний звʼязок |
| Що треба задати | k | eps, min_samples | звʼязок; кількість груп — після побудови |
| Форми кластерів | лише опуклі, межі прямі | будь-які | одиночний — будь-які, Ворда — кулясті |
| Що робить із дивними точками | приписує до найближчого центра | окрема мітка «шум» | лишає крихітними групами на великій висоті |
| Скільки рядків витримує | мільйони | мільйони (з індексом) | десятки тисяч |
| Новий обʼєкт без перерахунку | так | ні | ні |
| Головна пастка | випадковий старт, потреба знати k | підбір eps, різна щільність | вибір звʼязку міняє все |
Практичний порядок дій, який працює в більшості випадків: почни з
ієрархічної на підвибірці в кілька тисяч рядків, подивись на дендрограму — вона
покаже, скільки груп узагалі варто шукати. Далі, якщо групи схожі на грудки, візьми
k-means на всіх даних із цим k. Якщо на дендрограмі видно щось витягнуте або якщо
цікавлять саме дивні обʼєкти — бери DBSCAN і підбирай eps за коліном.
Лишилось одне питання, яке ми весь час обходили: усі картинки цієї теми
двовимірні, бо намалювати можна лише два виміри. А оголошення описується сімома числами,
клієнт банку — сотнею. Дивитись на кластери в семи вимірах ніхто не вміє — і саме тому
наступна тема про
метод головних компонент: як стиснути багато ознак у
дві так, щоб на них можна було подивитись і побачити те, що справді є в даних. А після
неї — пошук аномалій, куди веде мітка −1 із цієї теми.
practice.ipynb ми напишемо
DBSCAN із нуля й звіримо мітки з бібліотечним; проженемо всі три методи на трьох формах і
складемо таблицю з ARI; підберемо eps за графіком k-ї відстані; порівняємо
чотири звʼязки на одних даних; побудуємо дендрограму через
scipy.cluster.hierarchy; і наприкінці прикладемо всі три методи до справжньої
дошки оголошень і чесно звіримо результат із колонкою шахрайське.Далі в темі
Теорію прочитано. Тепер закріпи її на практиці.