Надто повільний повторний підрахунок найближчого сусіда для мільйонів точок даних


14

У мене є набір даних, що складається з мільйонів точок даних у 3D. Для обчислення, який я роблю, мені потрібно обчислити сусід (пошук діапазону) до кожної точки даних у радіусі, спробувати помістити функцію, обчислити помилку для придатності, повторити це для наступної точки даних тощо. Мій код працює належним чином, але це потребує дуже довго часу, приблизно 1 секунда за точку даних! Це, мабуть, тому, що для кожної точки він повинен шукати цілий набір даних. Чи є спосіб я зробити процес швидким. У мене є думка, що якщо я можу якось встановити якісь стосунки сусідства між першими сусідами, то це може бути менш повільним. Якщо це допомагає, я намагаюся знайти оптимальну ширину вікон Парзен в 3D.

Відповіді:


9

Я б запропонував googling для обмеження ієрархій обсягів (зокрема, дерево BSP). З огляду на вашу хмару точок, ви можете знайти площину, яка розбиває її на два рівні підклади. Тоді, коли вам потрібно знайти набір точок, які знаходяться в деякому радіусі R тестової точки, ви можете спочатку порівняти свою тестову точку з цією площиною, і якщо її висота вище, ніж R, то весь підкладок нижче площини також має бути далі, ніж R (також вам не потрібно перевіряти жодну з цих точок). Ви також можете застосовувати цю ідею рекурсивно, в кінцевому підсумку породжуючи складності n log n типу замість n-квадрата. (Це розділення BSP / бінарного простору,


7

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

Зокрема, R-дерева (та спеціалізовані форми, такі як R * -берези ) та X-дерева . Багато варіантів, оптимізованих для дещо іншого використання.

Вибір R *-дерева, а не наївного найближчого сусіда, був важливою частиною мого отримання фактора 10000 прискорення з певного коду. (Добре, можливо , кілька сотень , що було R * -tree, більшість інших тому , що наївний погляд вгору був сильно закодований таким чином, що він розбив кеш. :: зітхати :: )

О(Nжурнал⁡N)NО(журнал⁡N)


5

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

Там ми використовуємо списки комірок (або списки сусідів ), щоб допомогти нам зрозуміти, що знаходиться поруч; для цього додатка список комірок, мабуть, простіший алгоритм використання:

  • Розділіть ящик на ряд комірок.
  • Для кожної частинки визначте, якій клітині її слід призначити (O (1) на частинку).
  • Потім для кожної частинки перевірте "власну" клітинку плюс сусідні клітини; якщо будь-яка з них зайнята, подальший пошук не потрібен.
  • Якщо всі найближчі сусіди порожні, то перейдіть до наступних найближчих сусідів тощо, поки не знайдеться частинка.

Якщо у вашій системі є більш-менш рівномірний розподіл частинок, це значно знизить вартість вашого алгоритму, відповідно до грубості сітки. Однак необхідна тонка настройка: занадто груба сітка і ви не заощадите багато часу; занадто добре, і ви витратите багато часу на велосипеді по порожніх сітках!


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

Це правда у випадку МД; тут ми не знаємо, що це радіус апріорі .
— aeismail

Аналогічна схема тривалий час використовувалася в симуляції гравітації хмарних часток. Я не знаю, чи це все ще є частиною найсучаснішого.
— dmckee --- кошеня колишнього модератора

4

Ви обов'язково повинні перевірити дерева KD та октриси, які є методами вибору для точкових наборів (тоді як BSP - для загальних об'єктів, а сітки для більш-менш однакової щільності). Вони можуть бути дуже компактними і швидкими, мінімізуючи накладні витрати як в пам'яті, так і в обчисленні, і їх легко здійснити.

Коли ваші точки більш-менш рівномірно розподілені (навіть з порожніми ділянками, але не повинно бути особливості щільності або інших високих концентрацій), перевірте сферичні упаковки, якщо ви хочете спробувати неієрархічний підрозділ простору, подібний до сітки.


3

Ви, напевно, повинні розглянути можливість побудови триангуляції Делоне (ну, його аналог 3D). У 2D це спеціальна тріангуляція точок даних, яка завжди містить найближчого сусіда. Те ж саме в 3D, але з тетраедрами.

Ви можете будувати раз і назавжди триангуляцію, а потім шукати найближчого сусіда безпосередньо в тріангуляції. Я думаю, що є кілька хороших алгоритмів побудови триангуляції: у 2D побудова триангуляції внжурнал⁡(н) і пізніші пошуки найближчого сусіда лінійні за кількістю точок даних.

Сподіваюся, це допомагає!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.