I. Метрика відстані
По-перше, кількість функцій (стовпців) у наборі даних не є фактором вибору метрики відстані для використання в kNN. Існує досить багато опублікованих досліджень, спрямованих саме на це питання, і звичайними основами для порівняння є:
основний статистичний розподіл ваших даних;
взаємозв'язок між функціями, що містять ваші дані (чи незалежні вони - тобто як виглядає матриця коваріації); і
простір координат, з якого отримані ваші дані.
Якщо у вас немає попередніх знань про розподіл (и), з яких були відібрані ваші дані, принаймні одне (добре задокументоване та ретельне) дослідження робить висновок, що евклідова відстань є найкращим вибором.
Євклідова метрика використовується в мега-масштабних двигунах веб-рекомендацій, а також у сучасних наукових дослідженнях. Відстані, обчислені Евклідовим, мають інтуїтивне значення, а шкали обчислення - тобто, евклідова відстань обчислюється однаково, незалежно від того, чи є дві точки в двомірному просторі або в двадцяти двох розмірному просторі.
Мене кілька разів не вдалося, кожен з цих випадків евклідової відстані провалився, оскільки нижня (декартова) система координат була поганим вибором. І зазвичай ви це визнаєте, оскільки, наприклад, довжина шляху (відстані) більше не є додатковою, наприклад, коли метричний простір є шаховою дошкою, відстань на Манхеттені краще, ніж евклідова, так само, коли метричний простір є Землею, а ваші відстані переходять -континентальні польоти, відстань-метрика, яка підходить для полярної системи координат, є хорошою ідеєю (наприклад, Лондон - Відень - 2,5 години, Відень - Санкт-Петербург - ще 3 години, більш-менш в тому ж напрямку, але Лондон - Санкт-Петербург . Навпаки в Петербурзі не 5,5 годин, це трохи більше 3 годин.)
Але крім тих випадків, коли ваші дані належать до некартезіанської системи координат, вибір метрики відстані, як правило, не є істотним. (Дивіться цю публікацію в блозі від студента CS, порівнюючи декілька дистанційних показників, вивчаючи їх вплив на класифікатор kNN - квадрат чі дає найкращі результати, але відмінності не великі; Більш всебічне дослідження знаходиться в науковій роботі, Порівняльне вивчення Функції відстані для найближчих сусідів - махаланобіс (по суті євклідовий, нормалізований для врахування коваріації розмірів) був найкращим у цьому дослідженні.
Одне важливе застереження: щоб обчислення метричних обчислень були значимими, ви повинні переробити масштабваші дані - рідко можливо побудувати модель kNN для створення точних прогнозів, не роблячи цього. Наприклад, якщо ви будуєте модель kNN для прогнозування спортивних показників, а вашими змінними очікуваннями є висота (см), вага (кг), жир (%) та пульс спокою (удари в хвилину), то типова точка даних може бути виглядають приблизно так: [180.4, 66.1, 11.3, 71]. Очевидно, що в обчисленні відстані буде домінувати висота, тоді як внесок жирової маси в% буде майже незначним. По-іншому, якби замість цього дані повідомлялися по-різному, щоб маса тіла була в грамах, а не в кілограмах, то початкове значення 86,1 склало б 86 100, що мало б великий вплив на ваші результати, саме це і є Не хочу.
X_new = (X_old - mu) / sigma
II. Структура даних
Якщо ви стурбовані роботою структури kd-tree, A Voronoi Tessellation - це концептуально простий контейнер, але це дозволить різко покращити продуктивність і масштабувати краще, ніж kd-Trees.
Це не найпоширеніший спосіб збереження даних про навчання kNN, хоча застосування VT для цієї мети, а також наступні переваги в роботі є добре задокументованими (див., Наприклад, цей звіт Microsoft Research ). Практичне значення цього полягає в тому, що, якщо ви використовуєте "основну" мову (наприклад, в індексі TIOBE ), тоді вам слід знайти бібліотеку для виконання VT. Я знаю, що в Python і R є кілька варіантів для кожної мови (наприклад, пакет voronoi для R доступний на CRAN )
Використання VT для kNN працює так:
Зі своїх даних виберіть випадковим чином w пунктів - це ваші центри Вороного. Осередок Вороного інкапсулює всі сусідні точки, які є найближчими до кожного центру. Уявіть, якщо ви призначите різний колір кожному з центрів Вороного, так що кожна точка, призначена даному центру, буде пофарбована цим кольором. Поки ви маєте достатню щільність, це робити добре покаже межі кожного центру Вороного (як межа, яка розділяє два кольори).
Як вибрати центри Вороного? Я використовую два ортогональних настанови. Після випадкового вибору w точок, обчисліть ПТ для ваших навчальних даних. Далі перевірте кількість точок даних, присвоєних кожному центру Вороного - ці значення повинні бути приблизно однаковими (з урахуванням рівномірної щільності точок у вашому просторі даних). У двох вимірах це призведе до того, що ПТ з плитками однакового розміру. Це перше правило, ось друге. Виберіть w за допомогою ітерації - запустіть алгоритм kNN з w як змінним параметром та виміряйте продуктивність (час, необхідний для повернення прогнозу шляхом запиту на VT).
Тож уявіть, що у вас є один мільйон точок даних ..... Якби точки зберігалися в звичайній 2D структурі даних або в kd-дереві, ви б виконували в середньому по кілька мільйонів обчислень відстані для кожногонові точки даних, змінну відповідей яких ви хочете передбачити. Звичайно, ці обчислення проводяться на одному наборі даних. За допомогою V / T пошук найближчого сусіда проводиться в два етапи один за одним, проти двох різних груп даних - спочатку проти центрів Вороного, потім, коли знайдеться найближчий центр, точки всередині комірки відповідають цей центр шукають, щоб знайти фактично найближчого сусіда (за допомогою послідовних обчислень відстані). У поєднанні ці два пошуки набагато швидші, ніж один огляд грубої сили. Це легко зрозуміти: припустимо, що для точок даних 1М вибираєте 250 центрів Вороного, щоб тіселірувати свій простір даних. У середньому кожен осередок Вороного матиме 4000 точок даних. Тож замість того, щоб проводити середні 500 000 обчислень відстані (груба сила), ви виконуєте набагато менше, в середньому всього 125 + 2000.
ІІІ. Обчислення результату (прогнозована змінна відповідь)
Існує два етапи для обчислення прогнозованого значення з набору навчальних даних kNN. Перший - це визначення n або кількості найближчих сусідів, які слід використовувати для цього обчислення. Друга - як зважити їх внесок у передбачуване значення.
З / п / т першого компонента ви можете визначити найкраще значення n, вирішивши оптимізаційну задачу (дуже схожу на оптимізацію найменших квадратів). Ось така теорія; на практиці більшість людей просто використовують n = 3. У будь-якому випадку просто запустити свій алгоритм kNN над набором тестових примірників (для обчислення прогнозованих значень) для n = 1, n = 2, n = 3 тощо і побудувати графік помилки як функції n. Якщо ви просто хочете отримати правдоподібне значення для n, щоб розпочати роботу, знову ж таки, просто використовуйте n = 3.
Другий компонент - це зважування внеску кожного з сусідів (якщо вважати n> 1).
Найпростіша техніка зважування - це просто множення кожного сусіда на коефіцієнт зважування, який є просто 1 / (dist * K), або обернена відстань від цього сусіда до тестового примірника, часто помножене на деяку емпірично отриману константу, K. I Я не прихильник цієї техніки, тому що вона часто перевантажує найближчих сусідів (і, як наслідок, недостатньо важить більш віддалених); значення цього полягає в тому, що даний прогноз може майже повністю залежати від одного сусіда, що в свою чергу підвищує чутливість алгоритму до шуму.
Потрібна краща вагова функція, яка істотно уникає цього обмеження - це гауссова функція , яка в пітоні виглядає приблизно так:
def weight_gauss(dist, sig=2.0) :
return math.e**(-dist**2/(2*sig**2))
Щоб обчислити передбачуване значення за допомогою коду kNN, ви б ідентифікували n найближчих сусідів до точки даних, змінну відповіді яких ви хочете передбачити ('тестовий екземпляр'), а потім викликаєте функцію weight_gauss один раз для кожного з російських сусідів, передаючи на відстані між кожним сусідом тестовою точкою. Ця функція повертає вагу для кожного сусіда, яка потім використовується як коефіцієнт цього сусіда у підрахунку середньозваженого.