У меня есть облако точек из N точек в D-мерном пространстве с периодическими граничными условиями, где N может варьироваться от 500 до 10 ^ 8, а D может варьироваться от 1 до 20. Распределение точек сильно варьируется, от полностью однородного до очень сгруппированного все вместе. Для каждой точки в облаке точек мне нужно найти k ближайших соседей к этой точке. Мне также нужно найти, сколько точек существует на расстоянии каждой точки, в частности, максимальное расстояние. Мне не нужно знать, какие точки находятся в радиусе, сколько их, но это было бы хорошим дополнением.
Я пробовал kd-деревья, но они не обрабатывают границы переноса, а для больших деревьев дублирование неосуществимо. Кроме того, это становится медленным в более высоких измерениях.
Я только что натолкнулся на Vantage Point Trees и попробовал какой-то код, но он медленнее, чем kd-tree. Хотя код, который я нашел, использует рекурсивный метод поиска, без пакетной обработки. С одной стороны, он может обрабатывать условия обертки и не требует дублирования.
Я собираюсь посмотреть, смогу ли я выжать еще немного производительности из дерева VP, перейдя к итеративному подходу и посмотрев, смогу ли я выполнить пакетный поиск, но у меня была мысль. Все эти структуры данных работают для поиска ближайших соседей к произвольным точкам запроса, в то время как мои точки запроса ограничены тем, чтобы быть точками в облаке точек. Я полагаю, что это ограничение может предусматривать более производительную структуру (может быть, своего рода навигационная сетка?). Я пытался найти структуры, которые бы справились с этим, но мой гугл-фу меня подводит. Так что просто интересно, если кто-нибудь знает о структуре данных, которая может обрабатывать следующее:
Спасибо
Я сомневаюсь, что есть полный и определенный ответ на вашу очень сложную проблему, поэтому я просто делюсь своими мыслями.
Ваша спецификация проблемы сочетает в себе ряд вещей, которые плохо работают вместе (высокая размерность, неевклидова метрика, совершенно разные типы запросов). Если алгоритм должен принять общий случай, он обязательно медленный.
Давайте сначала разберемся со специальными случаями, когда известны хорошие структуры данных.
Если все это не относится (если вы имеете в виду практическое применение, пожалуйста, поделитесь с нами), ваш случай очень общий.
В дополнение к алгоритмам, которые вы упомянули, вы должны также попробовать геометрические деревья доступа к ближнему соседству (GNAT).
http://infolab.stanford.edu/~sergey/near.html
Они применяются к общим метрикам (включая вашу), а также обрабатывают неравномерное распределение.
Кроме того, я думаю, что ваши ожидания очень высоки. Вы можете сравнить с хорошей реализацией дерева kd (например, https://github.com/mariusmuja/flann), которая решает проблему только с евклидовой метрикой. Если это занимает много времени, не стоит ожидать, что более общие метрики будут решаться быстрее.
Следует признать, что более общий метод не может использовать ваше ограничение, что запросы являются точками в облаке. Мне было бы очень интересно, есть ли такое решение.
Если вариант Java (производительность похожа на C ++ в настоящее время), посмотрите на ELKI библиотека. Он обеспечивает реализации многочисленных многомерных индексов, включая подходы к уменьшению размерности и заполнению кривых. Он также предоставляет множество алгоритмов для kNN (евклидовых / неевклидных), обнаружения кластеров, запросов диапазона и т. Д. (Обычно вы можете определить свой собственный фильтр запросов с пользовательской метрикой расстояния).
Для КНН я могу специально рекомендовать CoverTree и (немного медленнее, но более общего назначения) PH-Tree, Я тестировал оба до 27 размеров. Дерево PH особенно подходит для кластеризованных и больших наборов данных (я протестировал более 100 000 000 точек). (Отказ от ответственности: PH-Tree основан на моих собственных исследованиях, но я думаю, что ваш вариант использования отлично подходит.)
Однако, насколько мне известно, ни один из этих подходов не обеспечивает особой оптимизации, как вы предложили.