Кластеризація k-means

Двадцять пʼять тем ми звіряли прогноз із правильною відповіддю. Тепер правильної відповіді немає — і з цього починається зовсім інша половина машинного навчання.

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

Це не поламана задача — це інша задача, і вона зветься навчанням без учителя (unsupervised learning). Замість «передбач відповідь» тут питають: яка структура є в цих даних сама по собі. Найпростіша форма такого питання — кластеризація (clustering): розкласти обʼєкти на групи так, щоб усередині групи вони були схожі між собою, а між групами — різні.

Працюватимемо на тій самій дошці оголошень про вживані телефони, що і в темі 08. Але задача інша. Там ми знали, які оголошення шахрайські, і шукали в даних сліди цієї відповіді. Тепер питання таке: які сегменти ринку існують на цій дошці обʼєктивно, за самою будовою даних, якщо ніхто нам нічого не розмічав?

ПостановкаЗадача без правильної відповіді

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

Зникає метрика в тому сенсі, до якого ти звик. F1, RMSE, ROC-AUC — усі вони рахують те саме: наскільки прогноз близький до правильної відповіді. Немає відповіді — немає й числа. Метрики для кластеризації існують (одну з них, силует, ми розберемо в розділі 6), але вони міряють форму розбиття: наскільки групи щільні й наскільки далеко одна від одної. Це не те саме, що «правильно».

Зникає поділ на навчальну й тестову частини. Ми ділили дані, щоб чесно поміряти якість на тому, чого модель не бачила (тема 03). Міряти тут нічого — кластеризацію будують одразу на всьому, що є.

Зникає єдина правильна відповідь. Ось найнезручніше. Ті самі оголошення можна розкласти на два сегменти й на пʼять, за ціною й за роком — і всі ці розбиття будуть однаково законними. Питання «а яке з них справжнє?» просто не має сенсу, бо справжнього немає. Є розбиття, корисні для конкретної задачі, і є марні.

Це не причіпка, а робочий факт. Якщо хтось показує кластеризацію зі словами «алгоритм знайшов чотири типи клієнтів», правильне питання — не «яка точність», а «чому чотири й що ти з цим зробиш». Кластеризація не відкриває істину; вона пропонує спосіб дивитись на дані.

Тоді навіщо вона взагалі? Через чотири речі, і кожна з них траплятиметься тобі частіше, ніж здається.

навіщощо саме роблятьприклад на нашій дошці
Сегментаціярозкласти обʼєкти на групи, з якими далі працюють по-різномудешеві старі телефони, свіжі дорогі, міцна середина — для кожного сегмента своя порада продавцеві
Стисненнязамінити обʼєкт номером його групи або координатами центразамість двох чисел на оголошення — один номер сегмента; так стискають кольори в зображеннях і сигнали в звуці
Розвідкапобачити будову даних до того, як ставити гіпотезичи є на дошці окрема група «майже нових дорогих» — чи це просто хвіст однієї великої хмари
Підготовкарозбити велику задачу на кілька менших або заповнити пропуски по групіпропущену ціну заповнити медіаною свого сегмента, а не всієї таблиці (тема 09)

Спільне в усіх чотирьох одне: результат оцінюють за тим, чи став кориснішим наступний крок, а не за збігом із розміткою.

Наші дані на цю тему такі. Беремо з дошки 1 100 оголошень, у яких є ціна (у решти вона пропущена, а кластеризація на відстанях без числа працювати не вміє), і рівно дві ознаки: ціну й рік випуску. Двох досить, щоб усе бачити на площині — а все, що буде сказано далі, справджується так само й для двадцяти ознак: у формулі відстані просто додається більше доданків, і жодне міркування від цього не міняється.

Ціну беремо не в гривнях, а як логарифм ціни. Причина стара й знайома з теми 10: різниця між 1 000 і 2 000 грн для покупця така сама, як між 10 000 і 20 000, а в гривнях це 1 000 проти 10 000. Логарифм робить ці дві відстані однаковими. Далі обидві ознаки приводимо до спільної шкали — z-оцінки: віднімаємо середнє, ділимо на стандартне відхилення. Чому це не порада, а обовʼязок, розберемо в розділі 7, і там буде видно, у що виливається пропуск цього кроку.

ІдеяІдея k-середніх

Метод k-середніх (k-means) описується одним абзацом, і це майже вся теорія.

Уся ідея. Виберемо k точок і назвемо їх центрами. Кожне оголошення припишемо до того центра, який до нього найближчий, — вийде k груп. Тепер кожен центр переїде туди, де насправді лежить середина його групи. Від цього дехто з оголошень опиниться ближче до сусіднього центра — перепишемо приналежність заново. І так по колу, поки перестане щось змінюватись.

Розберемо три слова, бо кожне щось приховує.

«Найближчий» — за звичайною евклідовою відстанню (euclidean distance). Це та сама відстань, яку на аркуші паперу дає теорема Піфагора. Дві ознаки — два катети: різниця по ціні й різниця по році. Відстань між точками — гіпотенуза: піднеси кожну різницю до квадрата, склади й візьми корінь. Скажімо, від точки (0.4; −0.3) до точки (1.0; 0.5) різниці дорівнюють 0.6 і 0.8, квадрати — 0.36 і 0.64, сума — 1.00, корінь — 1.00. Ознак більше двох — правило не міняється: квадрат різниці по кожній, усе додати, взяти корінь.

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

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

«k» — кількість груп, і її задаєш ти. Алгоритм її не шукає й не може знайти: скільки попросиш, стільки й нарисує. Це найважливіше обмеження методу, і розділ 6 цілком про нього.

Формально алгоритм (його звуть алгоритмом Ллойда) — це чотири рядки:

1. постав k центрів (поки що — навмання) 2. припиши кожну точку до найближчого центра 3. перерахуй кожен центр як середнє своїх точок 4. якщо приналежність змінилась — повернись до кроку 2

Усе. Ніякої оптимізації з підбором швидкості навчання, жодних похідних: два прості кроки по черзі — і вони самі сходяться. Чому саме сходяться, побачимо в розділі 4. Порівняй це з градієнтним спуском із теми 13: там модель дрібними кроками підкручувала свої числа в потрібний бік, і довжину кожного кроку треба було ще й правильно відміряти, інакше навчання або повзло, або розліталось. Тут немає ні кроків, ні їхньої довжини — і в цьому окрема краса методу.

РукамиТри ітерації руками

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

Обидві ознаки вже переведені в z-оцінки й округлені до одного знака, щоб арифметика лишалась читабельною. Нагадаю, як читати z: нуль — це середнє по всій дошці, −1 — на одне стандартне відхилення нижче, +1.5 — на півтора вище. Для ціни «нуль» — це приблизно 4 075 грн, для року — 2020-й.

A1 Alfa A5 2023 2 460 грн z = (−0.5, 1.1) A2 Alfa A7 2018 1 530 грн z = (−1.0, −1.1) A3 Alfa A5 2017 370 грн z = (−2.5, −1.5) A4 Alfa A5 2024 4 400 грн z = ( 0.1, 1.5) A5 Alfa A7 2024 7 320 грн z = ( 0.6, 1.5) A6 Alfa A5 2022 11 050 грн z = ( 1.1, 0.7) A7 Beta 12 2024 10 210 грн z = ( 1.0, 1.5) A8 Gamma X 2024 19 480 грн z = ( 1.7, 1.5) A9 Gamma X Ultra 2017 5 830 грн z = ( 0.4, −1.5) A10 Alfa A5 2019 620 грн z = (−2.0, −0.6)

Стартові центри поставимо в два реальні оголошення — A3 і A9. Вибір поганий: обидва з 2017 року, тобто обидва центри стоять на самому дні картинки. Це навмисно — так добре видно, як вони звідти виповзають.

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

Приклад 1 · відстань. Оголошення A1 має z = (−0.5, 1.1), центр K1 стоїть у (−2.5, −1.5). Різниця по першій ознаці: −0.5 − (−2.5) = 2.0. Різниця по другій: 1.1 − (−1.5) = 2.6. Квадрати: 4.00 і 6.76, сума — 10.76. Це і є перше число першого рядка таблиці. До K2 (0.4, −1.5) різниці дорівнюють 0.9 і 2.6, квадрати — 0.81 і 6.76, сума — 7.57. Сім менше за десять, отже A1 іде до K2.

Приклад 2 · новий центр. Після першої ітерації до K1 потрапили лише два оголошення: A3 (−2.5, −1.5) і A10 (−2.0, −0.6). Середнє по першій ознаці: (−2.5 − 2.0) ÷ 2 = −2.25. По другій: (−1.5 − 0.6) ÷ 2 = −1.05. Ось і центр K1 для другої ітерації — саме він стоїть у другому стовпці нижнього блоку таблиці.

Два правила, більше нічого. Уся таблиця нижче — це вони, повторені по черзі ще двічі.

Три ітерації, усі числа

Для кожного оголошення — квадрат відстані до першого й до другого центра. Менший із двох виділено: саме туди точка й іде.

ітерація 1 ітерація 2 ітерація 3
оголошенняz d² до K1d² до K2→ d² до K1d² до K2→ d² до K1d² до K2→
A1−0.5, 1.110.767.57K27.691.06K26.471.31K2
A2−1.0, −1.12.412.12K21.575.09K10.706.65K1
A3−2.5, −1.50.008.41K10.2713.18K10.6315.55K1
A40.1, 1.515.769.09K212.030.83K210.330.64K2
A50.6, 1.518.619.04K214.630.75K212.510.36K2
A61.1, 0.717.805.33K214.290.46K211.730.26K2
A71.0, 1.521.259.36K217.071.05K214.620.50K2
A81.7, 1.526.6410.69K222.112.35K219.071.51K2
A90.4, −1.58.410.00K27.234.62K25.185.81K1
A10−2.0, −0.61.066.57K10.277.44K10.259.16K1
центр K1−2.500, −1.500−2.250, −1.050−1.833, −1.067
центр K20.400, −1.5000.425, 0.6500.629, 0.900
інерція54.2613.2211.33
Як читати. Три нижні рядки — це центри, з якими рахувалась ця ітерація, і сума квадратів відстаней до свого центра при них. Після ітерації 3 центри стають (−1.275, −1.175) і (0.667, 1.300), сума падає до 9.07, а на четвертій ітерації жодна точка не змінює групу — алгоритм зупиняється.

Простеж очима три речі.

Перша: центри виповзають з дна. K1 пройшов шлях (−2.5, −1.5) → (−2.25, −1.05) → (−1.833, −1.067) → (−1.275, −1.175), K2 — (0.4, −1.5) → (0.425, 0.65) → (0.629, 0.9) → (0.667, 1.3). Ніхто їх не тягнув: кожен просто щоразу ставав середнім своїх точок.

Друга: приналежність міняється, і не один раз. На першій ітерації A2 пішло до K2, на другій повернулось до K1. A9 три ітерації трималось за K2 і перебігло до K1 аж на третій — там різниця була мізерна, 5.18 проти 5.81. Оголошення на межі перекидаються туди-сюди довше за всіх, і ми ще повернемось до A9 в розділі 6.

Третя: сума квадратів падає весь час — 54.26, 13.22, 11.33, 9.07. Вона й є те, що метод мінімізує, і зараз розберемось чому саме вона.

А тепер те саме, але на всіх 1 100 оголошеннях і з трьома центрами. Тисяча сто точок руками не порахуєш, зате видно те, чого не видно в таблиці, — як межі між групами переповзають картинкою.

Ітерації наочно

Тисяча сто оголошень, три центри, поставлені в три випадкові оголошення. Тисни «крок» і дивись, як точки перефарбовуються, центри переїжджають, а інерція спадає.

наступний півкрок
що будерозподілити точки
ітерація0
інерція—
зміна—
перебігло—
Осі. Горизонтальна — ціна оголошення, шкала логарифмічна (тому підписи 300 ₴, 1 000 ₴, 3 000 ₴ стоять на однаковій відстані). Вертикальна — рік випуску; років усього вісім, тому точки лягають вісьмома рядами. Тло залито областями центрів: у кожній точці екрана показано, який центр там найближчий. Саме ці області й переїжджають разом із центрами — і після півкроку «пересунути центри» частина точок опиняється у чужій за кольором області. Їх наступний півкрок і перефарбує.

ІнерціяЩо саме мінімізується

Ми жодного разу не сказали алгоритму, чого домагатись. А він домагається — і цілком конкретної величини. Вона зветься інерцією (inertia), і це сума квадратів відстаней від кожної точки до центра її власного кластера:

J = Σусі точки ‖ xi − c(кластер точки i) ‖²

Словами: візьми кожне оголошення, зміряй відстань до центра його групи, піднеси до квадрата, склади все. Символ xi — координати i-го оголошення, c — координати центра тієї групи, у яку воно потрапило, подвійні риски — довжина вектора між ними, тобто відстань. Що менша інерція, то щільніше точки тиснуться до своїх центрів.

Чому саме квадрат, а не сама відстань? Дві причини. Перша практична: квадрат позбавляє кореня, і все стає простішим. Друга змістовна: середнє арифметичне — рівно та точка, яка мінімізує суму квадратів відстаней. Не сума відстаней, а сума їхніх квадратів. Тобто крок «постав центр у середнє» — не інтуїція, а точний розвʼязок задачі мінімізації. Ось він у два рядки, для однієї ознаки:

крок 1 · що мінімізуємо

Шукаємо точку c, для якої сума квадратів відстаней до заданих чисел x1…xn найменша.

f(c) = (x1 − c)² + (x2 − c)² + … + (xn − c)²
крок 2 · де мінімум

Це парабола, вітками вгору: спершу спадає, потім зростає, і десь між тим має дно. У дна дотична горизонтальна — тобто похідна (швидкість, з якою функція міняється; ми користувались нею в темі 13) там дорівнює нулю. Прирівняймо її до нуля.

f ′(c) = −2(x1 − c) − … − 2(xn − c) = 0
крок 3 · відповідь

Ділимо на −2 і розкриваємо: сума всіх x мінус n·c дорівнює нулю. Отже:

c = (x1 + … + xn) ÷ n

Тобто середнє арифметичне. Для двох ознак те саме рахується окремо по кожній — вони в цій сумі не переплітаються.

Те саме без жодної похідної. Якщо слово «похідна» нічого тобі не каже, ось той самий висновок шкільною алгеброю. Розкрий дужки в сумі й згрупуй доданки — вона перепишеться як n · (c − m)² + S, де m — середнє наших чисел, n — скільки їх, а S — сума квадратів їхніх відхилень від m. У другому доданку c не бере участі взагалі: хоч куди став центр, S не зрушить. Отже зменшувати можна лише перший доданок, а квадрат ніколи не буває відʼємним і дорівнює нулю рівно тоді, коли c = m. Перевір на трьох числах 1, 2 і 6. Середнє — 3, сума квадратів відхилень від нього — 4 + 1 + 9 = 14. Постав центр не в 3, а в 4: (1−4)² + (2−4)² + (6−4)² = 9 + 4 + 4 = 17, тобто на 3 більше. І справді, n · (c − m)² = 3 · (4 − 3)² = 3. Зсув центра завжди коштує рівно стільки.

Куди поставити центр

Чотири оголошення групи «старі й дешеві» з розділу 3 — і сума квадратів відстаней до них як функція того, куди поставлено центр.

Дно параболи — рівно в середньому арифметичному. Куди центр не постав, сума квадратів вийде більша, ніж у точці −1.275, де вона дорівнює 4.91. І зсув коштує однаково в обидва боки: пів кроку ліворуч чи праворуч додає рівно 4 · 0.5² = 1.00. Тому крок «перерахуй центр як середнє» — не інтуїція, а точна відповідь на питання «де сума найменша».

Тепер видно, чому алгоритм узагалі сходиться. Кожен із двох кроків не збільшує інерцію:

Різних розбиттів на k груп скінченна кількість, інерція не зростає, а те саме розбиття двічі підряд означає зупинку. Тому алгоритм завжди закінчується за скінченне число кроків. На нашій десятці вистачило трьох ітерацій, на 1 100 оголошеннях — одинадцяти. І там, і там наступний прохід уже нічого не міняє й лише підтверджує зупинку.

І тут головна пастка. Ми довели, що інерція не зростає. Ми не довели, що вона доходить до найменшого можливого значення. Алгоритм зупиняється у першій же точці, де жоден із двох кроків уже нічого не міняє, — а таких точок багато, і вони різні. Це локальний мінімум: краще за сусідів, але не обовʼязково краще за всіх. Знайти справжній глобальний мінімум для k-means — задача, яку в загальному випадку ніхто швидко розвʼязувати не вміє.

І остання властивість інерції — та, через яку розділ 6 узагалі існує: з ростом k вона завжди спадає. Не «зазвичай спадає», а завжди, і ось чому. Візьми будь-яке розбиття на k груп і додай (k + 1)-й центр рівно в одну з точок — у будь-яку, аби вона не була центром уже. Ця точка тепер лежить на власному центрі, і її внесок у суму став нулем. Жодна інша точка при цьому не програла: кожна або лишилась при своєму старому центрі, або знайшла новий ближчим — а ближчий центр означає менший доданок, ніяк не більший. Сума зменшилась. Так само можна додати ще один центр, і ще; при k, рівному кількості оголошень, кожна точка стає власним центром, усі відстані нульові, і інерція дорівнює рівно нулю.

Звідси висновок, який визначить увесь розділ 6: питання «яке k дає найменшу інерцію» безглузде. Відповідь на нього завжди одна й та сама — найбільше можливе k, — і користі з неї нуль. Порівнювати за інерцією можна лише розбиття з однаковим k — саме так у наступному розділі ми відрізнимо вдалий старт від невдалого. А обирати саме k доведеться чимось іншим.

СтартРізний старт — різна відповідь

Локальний мінімум — не теоретичне застереження. Це те, з чим ти зіткнешся на першому ж запуску, і виглядає воно так: та сама функція, ті самі дані, два запуски — дві різні відповіді.

Ось чотири запуски k-means на наших 1 100 оголошеннях, k = 3. Різниця між ними тільки в тому, у які три оголошення поставлено початкові центри.

Чотири старти, чотири відповіді

Перемикай стартову розкладку. Порожні кружечки — де центри стояли спочатку, ромби — куди приїхали. Дивись на інерцію внизу праворуч.

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

Найкращий із чотирьох стартів дає інерцію 803.43, найгірший — 880.78. Це на 9.6 % більше, і різниця не косметична: у поганому розбитті одна група збирає дешеві телефони всіх років підряд, а «свіжі» й «старі» розлазяться по двох інших групах. Сегменти виходять інші, і бізнес-висновок із них теж інший.

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

k-means++ — розумний старт

Кидати центри повністю навмання погано тим, що два з них легко можуть упасти в ту саму щільну хмару, а віддалену групу не помітить ніхто. k-means++ ставить центри так, щоб вони одразу розійшлися:

1. перший центр — випадкове оголошення 2. для кожного оголошення рахуємо d² — квадрат відстані до найближчого вже обраного центра 3. наступний центр тягнемо випадково, але з імовірністю, пропорційною цьому d² 4. повторюємо, поки центрів не стане k

Тобто далекі від усіх обраних центрів точки мають найбільший шанс стати наступним центром. Випадковість лишається, але тепер вона зміщена в бік розкиданих стартів. У scikit-learn це параметр init="k-means++", і він стоїть за замовчуванням.

n_init — просто спробувати кілька разів

Другий прийом прямолінійніший: запустити алгоритм кілька разів із різних стартів і лишити той результат, у якого інерція найменша. Це параметр n_init. Порівнювати запуски між собою можна саме тому, що інерцію рахують без жодних міток.

Скільки ставити. У сучасних версіях за замовчуванням стоїть n_init="auto", і з k-means++ це один запуск. Поставити n_init=10 коштує майже нічого й помітно зменшує ризик випадково зупинитись у поганому мінімумі. І обовʼязково фіксуй random_state: без нього два запуски того самого коду дадуть різні кластери, і ти згаєш годину, шукаючи неіснуючу помилку у власних даних.

Скільки групСкільки брати кластерів

Найчастіше питання про k-means і найчесніша відповідь на нього: універсального способу немає. Є два інструменти, які звужують вибір, і жоден із них не звужує його до однієї цифри.

Метод ліктя

Побудуємо інерцію для k від 1 до 10. Вона спадає завжди — це ми вже знаємо. Але спадає нерівномірно: спочатку кожен новий кластер приносить величезну користь, а потім уже майже ніякої. Точка, де крива з обриву переходить у пологий схил, і зветься ліктем.

Ось падіння інерції на наших даних, крок за кроком:

k = 1 → 2 інерція 2200.0 → 1069.7 впала на 1130.3 k = 2 → 3 інерція 1069.7 → 803.4 впала на 266.2 k = 3 → 4 інерція 803.4 → 573.9 впала на 229.6 k = 4 → 5 інерція 573.9 → 480.6 впала на 93.2 k = 5 → 6 інерція 480.6 → 392.2 впала на 88.4 k = 6 → 7 інерція 392.2 → 347.8 впала на 44.4

Де тут лікоть? Найбільший обвал — на другому кластері, але це нікому не цікаво: розбиття на дві групи буває корисним завжди. Далі два кроки поспіль дають схожу користь (266 і 230), а потім користь одразу падає більш ніж удвічі (93). Тобто лікоть десь на четвірці — але «десь», бо між 3, 4 і 5 крива згинається плавно, і три різні люди покажуть пальцем у три різні точки.

Це не вада наших даних. Різкий лікоть буває тоді, коли в даних справді є кілька відокремлених грудок — а в реальних таблицях вони частіше зливаються в одну хмару зі згущеннями. Метод ліктя чесно показує саме це.

Силует

Другий інструмент дивиться не на суму відстаней, а на кожну точку окремо й питає: чи вона взагалі в тій групі, у якій має бути? Величина зветься силуетом (silhouette). Для точки i беруть дві середні:

s = (b − a) ÷ max(a, b)

Ділення на більше з двох тримає результат у межах від −1 до +1, і читається він так:

Порахуймо силует руками для оголошення A9 — того самого Gamma X Ultra 2017 року за 5 830 грн, яке дві ітерації вагалось між групами. У фінальному розбитті десятки воно опинилось у групі «старі й дешеві» разом із A2, A3 і A10.

Силует однієї точки

Десять оголошень із розділу 3, фінальне розбиття. Бірюзові відрізки — відстані до своїх, рожеві — до чужих.

Дві середні — і одна різниця. Відстані до своїх: 1.456, 2.900, 2.563 → a = 2.306. Відстані до шести чужих: 2.751, 3.015, 3.007, 2.309, 3.059, 3.270 → b = 2.902. Отже s = (2.902 − 2.306) ÷ 2.902 = 0.205. Для порівняння, у A5 (Alfa A7 2024 року) a = 0.823, b = 3.429 і s = 0.760. Середній силует по всіх десяти — 0.581.

0.205 — майже нуль, і це чесно описує становище A9: телефон дорогий, як у «свіжих», а рік як у «старих». Алгоритм мусив кудись його віднести й відніс, але впевненості в цьому рішенні немає ніякої.

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

Вибір k

Тягни повзунок. Ліворуч — саме розбиття, знизу — крива інерції (лікоть) і крива силуету. Вони показують на різні числа.

інерція803.4
силует0.384
падіння266.2
найм. група264
Найбільший середній силует — при k = 2 (0.444). Лікоть на кривій інерції читається радше як k = 4. Обидва числа пораховані чесно, і вони не збігаються. Побачити на кривій силуету другий горбик при k = 7 (0.401) теж корисно: це майже завжди не «сім справжніх сегментів», а один крихітний щільний кластер, який підняв середнє.

Отже, лікоть каже 4, силует каже 2, і жоден із них не бреше. Так буває частіше, ніж навпаки — і з цього треба зробити правильний висновок, а не шукати третю метрику як арбітра.

Останнє слово за задачею, а не за метрикою. Ці два числа окреслюють розумний діапазон: десь від 2 до 5, а не 30. Усередині діапазону вибирає людина, і критерій у неї інший — з чим я зможу працювати. Нам для дошки оголошень потрібні сегменти, які можна назвати словами й показати менеджерові, тому далі беремо k = 3. Це рішення, і воно записане як рішення, а не видане за відкриття.

Ось що дають ці три сегменти при k = 3 (нагадаю: центр — вигадана «типова» точка групи, а не конкретне оголошення; на фігурах ті самі центри округлені до десятків гривень, щоб підписи були коротші):

сегментоголошеньцентряк це читається
Дешеві старі3551 478 грн · 2018.9телефони, які дослужують останній рік; ціна нижча за дві тисячі
Міцна середина2645 795 грн · 2018.6той самий вік, але дорожчі моделі — колишній верхній сегмент, що подешевшав
Свіжі дорогі4817 098 грн · 2022.7усе, що молодше за 2021 рік, від бюджетних до найдорожчих

Назви придумали ми; алгоритм видав тільки номери. І зверни увагу на асиметрію: старі телефони він поділив надвоє за ціною, а свіжі лишив однією групою. Серед старих розкид цін більший — за пʼять років дешеві й дорогі моделі розійшлись, а свіжі ще тримаються купи.

МасштабМасштаб ознак обовʼязковий

Ми двічі мимохідь сказали «приводимо ознаки до z-оцінок». Настав час показати, що буває, якщо цього не зробити, — бо це найпоширеніша й найтихіша помилка в кластеризації.

k-means не знає, що таке гривня й що таке рік. Він знає тільки числа, з яких рахує відстань. Подивись на розкид наших двох колонок у їхніх власних одиницях:

ціна стандартне відхилення 8 685 грн рік стандартне відхилення 2.31 року

Різниця у 3 765 разів. У формулі відстані обидві різниці підносяться до квадрата й додаються — отже, доданок від ціни у мільйони разів більший за доданок від року. Ознака «рік» присутня у формулі й не впливає ні на що.

Одні й ті самі дані, два масштаби

Ліворуч — k-means на сирих гривнях і роках. Праворуч — на тих самих даних, приведених до z-оцінок. Колір = кластер.

Ліворуч рік не впливає ні на що. Кожен із трьох кластерів містить оголошення всіх років з 2017-го по 2024-й, а межі між ними — вертикальні лінії по ціні: до 11 390 ₴, далі до 45 320 ₴, далі решта. Причому цінові смуги виходять безглузді: у першій сидять 956 оголошень із 1 100, в останній — 8. Праворуч — те саме після масштабування. Збіг двох розбиттів між собою — на рівні випадкового перемішування: число, яким цей збіг міряють, розберемо в розділі 9, і тут воно дорівнює −0.004.

Зверни увагу на ліву картинку уважніше. Річ не тільки в тому, що рік проігноровано. Сама ціна поділена так, що користі з цього нуль: 956 оголошень в одній купі, 8 — в окремому кластері. Причина в тому, що кілька дуже дорогих оголошень (колекційні Gamma X і одруки із зайвим нулем, знайдені ще в темі 08) відтягли на себе цілий центр.

Правило без винятків. Будь-який метод, який рахує відстані — k-means, ієрархічна кластеризація і DBSCAN із наступної теми, а далі в курсі й моделі з учителем, що спираються на відстань, — вимагає приведення ознак до спільної шкали. Не «бажано», а вимагає: без цього результат визначає та колонка, у якої випадково виявились найбільші числа. І зверни увагу, що тут, на відміну від теми 09, немає ризику витоку через масштабування на всіх даних — тесту немає, ділити нічого. Це один із небагатьох випадків, коли fit_transform на всій таблиці — правильно.

Логарифм ціни при цьому не заміна масштабуванню, а окремий крок: він зменшує хвіст, щоб кілька оголошень по 80–95 тисяч не перетягнули на себе центр, а z-оцінка потім зрівнює шкали. Потрібні обидва.

МежіЧого k-means не вміє

У самій будові методу заховане припущення, яке ніде не написане, але діє завжди. Кожна точка йде до найближчого центра — отже, межа між двома кластерами завжди пряма (у трьох вимірах — площина). Кластер, який отримує k-means, — це опукла область навколо свого центра, приблизно кругла. Опукла означає ось що: візьми будь-які дві точки цієї області й проведи між ними відрізок — він увесь лежить усередині. Кільце, підкова чи літера S опуклими не бувають, і жодним k-means їх не зібрати.

Звідси й обмеження: k-means добре знаходить кулясті групи приблизно однакового розміру. Коли групи в даних влаштовані інакше, він усе одно щось поверне — і це «щось» буде очевидно неправильним для людського ока.

Три випадки, де відповідь очевидно неправильна

У кожному наборі людина бачить групи одразу. Кольори — те, що знайшов k-means при k = 2.

Що сталось у кожному випадку. Витягнуті: дві довгі смуги лежать одна над одною, а k-means розрізав їх упоперек — зі 130 точок на своїх місцях лише 58 %. Вкладені кола: внутрішнє коло й кільце навколо нього. Центри двох справжніх груп тут лежать в одній точці — у спільній середині, — тому жодна пряма межа їх не розділить; два ромби на картинці це вже центри, які k-means поставив натомість, розрізавши обидві групи навпіл. На своїх місцях — 60 %. Різна щільність: щільна купка ліворуч і розсіяна хмара праворуч; межа проходить надто далеко праворуч і 16 точок розсіяної групи з 55 відходять до щільної — 89 %.

Найкорисніше в цій схемі — середній випадок. Дві групи, які людина розрізняє миттєво, для k-means не відрізняються взагалі, бо їхні центри в одній точці. Жодне k, жоден n_init і жоден random_state цього не полагодять: тут не пощастило з методом, а не з налаштуваннями.

Є ще три речі, про які варто знати заздалегідь.

ПеревіркаЧи означають кластери щось

Тепер найчесніша частина теми. У нашій таблиці все-таки є колонка шахрайське — та сама розмітка, з якою ми розбирали дошку ще в темі 08. Алгоритм її не бачив: він працював лише з ціною й роком. Подивімось, чи має знайдене розбиття хоч якийсь стосунок до неї. По дошці загалом шахрайських оголошень 12.6 % — 139 із 1 100.

сегментусьогочеснихшахрайськихчастка
Дешеві старі3552827320.6 %
Міцна середина264246186.8 %
Свіжі дорогі4814334810.0 %

Сигнал є — і він слабкий. У найдешевшому сегменті шахрайських утричі більше, ніж у «міцній середині». Але жоден із трьох кластерів не є «кластером шахраїв»: навіть у найгіршому з них чотири оголошення з пʼяти чесні.

Спокуса тут очевидна: оголосити перший сегмент детектором шахрайства. Порахуймо, що з цього вийде, тими самими метриками, що й у темі 05. Якщо вважати «дешеві старі» прогнозом «шахрайське»:

наш «детектор» precision 0.206 recall 0.525 F1 0.296 навмання, 355 рядків precision 0.126 recall 0.323 F1 0.182

Другий рядок — це орієнтир, без якого перший нічого не означає. Уяви, що ми не кластеризували нічого, а просто ткнули пальцем у 355 оголошень навмання — стільки ж, скільки в найдешевшому сегменті. Шахрайських серед них виявиться приблизно стільки ж, скільки й по всій дошці, тобто 12.6 %. Ось і вся точність випадкового тику.

Наш сегмент дає 20.6 %. Це справді краще за жеребкування, але не в рази: кластер знає щось про шахрайство, і знає мало. Практичний бік ще сумніший — «детектор» упіймав половину шахраїв, але з кожних пʼяти піднятих тривог чотири хибні. Модератор, якому дати такий список, чотири рази з пʼяти читатиме чесне оголошення.

Є ще один орієнтир, з яким ми зустрілись у темі 05: модель, яка каже «усі оголошення чесні». Вона не піднімає жодної тривоги, тож помиляється рідше за наш сегмент — 12.6 % помилок проти 32 % — і при цьому не знаходить нікого взагалі. Recall у неї нуль. Саме тому «частка правильних відповідей» тут ні про що не говорить, а precision і recall — говорять.

Шахрайські в кожному сегменті

Кожен сегмент — сто відсотків своїх оголошень. Зафарбована частина — шахрайські. Пунктир — частка по всій дошці.

Жоден сегмент не є кластером шахраїв. Перекіс між «дешевими старими» і «міцною серединою» справді триразовий, але в масштабі цілого сегмента його майже не видно: навіть у найгіршому з трьох чотири оголошення з пʼяти чесні, і пунктир випадкового тику проходить недалеко від кожної смуги. Так виглядає слабкий сигнал — і його легко сплутати з відкриттям, якщо дивитись на самі відсотки без цієї лінії.

Є й одне число, яке підсумовує все відразу. Скоригований індекс Ренда (adjusted Rand index) міряє, наскільки два розбиття тих самих обʼєктів схожі: 1 — повний збіг, 0 — збіг рівно такий, який дало б випадкове перемішування. Між нашими кластерами й колонкою шахрайське він дорівнює 0.007.

Скажемо це прямо. Кластеризація не знайшла шахраїв. Вона й не мала: шахрайство на цій дошці — не окрема область простору, а співвідношення ціни оголошення з типовою ціною такого самого телефона. У ознаках «ціна» й «рік» цього відношення просто немає — його треба спершу побудувати руками: ознака «наскільки ціна відхиляється від типової для цієї моделі телефона» — рівно те, чого кластеризації бракує. Далі таку ознаку віддають моделі з учителем — дереву рішень, лісу чи бустингу, — і ця сама дошка починає видавати шахраїв. Без розмітки цього не зробити ніяк.

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

Тому знайдені кластери завжди перевіряють двома питаннями. Перше: чи можу я описати кожну групу словами так, щоб людина з предметної області кивнула? «Дешеві старі телефони» — так. «Кластер номер два» — ні. Друге: чи стійкі вони? І це не заклик, а вимірювання: прибери десять відсотків рядків навмання, перезапусти кластеризацію на решті — і звір нове розбиття зі старим на спільних рядках тим самим скоригованим індексом Ренда. Повтори кілька разів, щоразу викидаючи іншу десятину. Якщо індекс щоразу близький до одиниці, розбиття описує дані. Якщо він стрибає, воно описує конкретний запуск, і показувати його менеджерові як «сегменти ринку» не можна.

ДаліЩо далі

k-means потребує від тебе трьох речей, і всі три ти тепер знаєш: задати k, привести ознаки до спільної шкали й перевірити, що результат не залежить від щасливого старту. Він дає кулясті групи приблизно однакового розміру, і коли групи в даних не такі — мовчки дає неправильну відповідь.

Обидва його обмеження мають прямі відповіді, і саме з них починається наступна тема.

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

І ще одна пара, яка добре працює разом. Ознак у нас тут було дві — рівно щоб усе малювалось на площині. Коли їх двадцять, кластери нікуди не діваються, а от подивитись на них уже не можна. Тоді в діло йде метод головних компонент із теми 11: стиснути двадцять ознак у дві, намалювати — і аж тоді дивитись, чи схожі знайдені групи на групи.