Алгоритм нахождения совокупной массы структур типа «гранола-батончик»?

19

Я - исследователь планетных наук, и один проект, над которым я работаю, это N- тело симуляции колец Сатурна. Цель данного конкретного исследования - наблюдать, как частицы слипаются друг с другом под действием собственной гравитации, и измерять совокупную массу сгустков в зависимости от средней скорости всех частиц в клетке. Мы пытаемся выяснить, может ли это объяснить некоторые наблюдения, сделанные космическим кораблем Кассини во время летнего солнцестояния Сатурна, когда были замечены крупные сооружения, отбрасывающие тени на кольца почти с ребра. Ниже приведен скриншот того, как выглядит любой данный временной шаг. (Каждая частица имеет диаметр 2 м, а сама ячейка моделирования имеет ширину около 700 м.)

Ячейка _N_-тела симуляции колец Сатурна с частицами, изображенными в виде крошечных заштрихованных сфер на черном фоне.

Код, который я использую, уже выдает среднюю скорость на каждом шаге. Что мне нужно сделать, так это найти способ определить массу частиц в сгустках, а НЕ рассеянные частицы между ними. Я знаю положение каждой частицы, массу, размер и т. Д., Но я не могу легко понять, что, скажем, частицы 30 000-40 000 вместе со 102 000 105 000 составляют одну нить, которая для человеческого глаза очевидна.

Итак, алгоритм, который мне нужно написать, должен быть кодом с как можно меньшим количеством введенных пользователем параметров (для воспроизводимости и объективности), который будет проходить через все положения частиц, выяснять, какие частицы принадлежат сгусткам, а затем вычислять масса. Было бы замечательно, если бы он мог сделать это для «каждого» сгустка / нити, в отличие от всего, что происходит в камере, но я не думаю, что мне на самом деле нужно это для их разделения.

Единственное, о чем я думал, - это какое-то вычисление расстояния N 2, где я вычислял бы расстояние между каждой частицей, и если, скажем, ближайшие 100 частиц находились в пределах определенного расстояния, то эта частица считалась бы частью кластер. Но это кажется довольно неаккуратным, и я надеялся, что вы, ребята из CS и программисты, возможно, найдете более элегантное решение?


Отредактировано с помощью My Solution: я выбрал своего рода подход «ближайший сосед / кластер» и сначала выполнил реализацию N 2 «quick-n-dirty» . Итак, возьмите каждую частицу, вычислите расстояние до всех других частиц, и порог для в кластере или нет, был ли N частиц на расстоянии d (два параметра, которые, к сожалению, должны быть установлены априори , но, как говорили некоторые ответы / комментарии, я не собирался сойти с рук не имея некоторых из них).

Затем я ускорил его, не сортируя расстояния, а просто выполняя поиск N и увеличивая счетчик для частиц в пределах d , и это ускорилось в 6 раз. Затем я добавил «дерево тупого программиста» (потому что я знаю, почти ничего о кодах деревьев). Я делю ячейку моделирования на заданное количество сеток (наилучшие результаты, когда размер сетки ≈7 d ), где основная сетка совпадает с ячейкой, одна сетка смещена на половину по x и y , а две другие смещены на 1/4 дюйма ± х и ± у . Затем код делит частицы на сетки, тогда каждая частица N должна рассчитывать только расстояния до других частиц в этой ячейке.

Теоретически, если бы это было реальное дерево, я должен получить порядок N * log ( N ), а не N 2 скоростей. Я оказался где-то посередине, где для подмножества из 50 000 частиц я увеличил скорость в 17 раз, а для ячейки из 150 000 я получил скорость в 38 раз. 12 секунд для первого, 53 секунды для второго, 460 секунд для ячейки с 500 000 частиц. Эти скорости сопоставимы с тем, сколько времени занимает код, чтобы запустить симуляцию на 1 шаг вперед, так что это разумно на данный момент. О - и это полностью потоковое, так что потребуется столько процессоров, сколько я могу на него бросить.

Стюарт Роббинс
источник
3
Я не особо разбираюсь в этом вопросе, поэтому я сам мало что могу предложить, но читали ли вы статью в Википедии о кластерном анализе ? Кажется, это очень активная область изучения.
Коул Кэмпбелл
Я настороженно отношусь к кластерному коду, по крайней мере к чему-то вроде DBSCAN, потому что я думаю, что он «следовал бы» за некоторыми тонкими нитями, которые, как я знаю, визуально не являются частью кластеров, но могут быть алгоритмически. У меня есть опыт работы с кодами типа DBSCAN, поскольку я использую его для своей другой работы - изучения кратеров.
Стюарт Роббинс
1
Любой код, который идентифицирует нити, подобные этому, почти наверняка будет иметь какую-то настройку «чувствительности».
Роберт Харви
2
Согласовано. Настоящая трудность здесь заключается в том, что термин «глыба» не является четко определенным термином. В конце дня вам нужно будет использовать какой-то алгоритм кластерного анализа (который, на самом деле, ваше предлагаемое решение уже есть), возможно, в сочетании с каким-то этапом снижения шума.
Коул Кэмпбелл
2
это может помочь, если вы нарисуете на своем изображении то, что, по вашему мнению, является действительным скоплением (и, возможно, недействительным)
jk.

Ответы:

3

Мое первое предложение - разбить вашу проблему на две проблемы: сначала выясните, чего вы хотите, а затем выясните, как эффективно получить то, что вы хотите. Вы не можете эффективно получить то, что вы еще не определили. В этом ответе я приведу несколько идей, которые могут помочь вам найти это определение. Я предлагаю вам сначала сделать неэффективную реализацию идей, которые вам нравятся, применить их к нескольким не слишком большим наборам данных, вручную оценить результаты, адаптировать свое определение и повторить (возможно, задав еще один вопрос здесь), пока вы не будете удовлетворены ваше определение. После этого я предлагаю вам задать еще один вопрос о том, как эффективно рассчитать результат вашего определения (если вам все еще нужна помощь).

Итак, давайте посмотрим, что будет соответствовать нашему интуитивному представлению о «пряди». Кажется, что ваши нити состоят из примерно равномерно распределенных точек, хотя вы должны проверить это, сделав увеличенное изображение (исходного набора данных) - разрешение вашей фотографии слишком низкое, чтобы с уверенностью сказать, что точки действительно распределены примерно равномерно , Я предполагаю, что они для этого ответа.

Первоначальной идеей может быть поиск ближайшего соседа в каждой точке. Давайте выберем точку X, назовем ее ближайшего соседа Y и установим D в качестве расстояния между X и Y. Затем мы посмотрим на окружность C вокруг X с радиусом D * A, где A - параметр настройки, скажем, A = 3. Если X является частью цепи, мы ожидаем, что для каждой точки Z в C расстояние от Z до ближайшего соседа W примерно такое же, как D. Если оно значительно короче, скажем, больше, чем A (или, может быть, какой-то другой параметр B) тогда X, по-видимому, близко к точкам, которые намного ближе друг к другу, чем к X, поэтому X, вероятно, не является частью цепи.

Этот критерий не является полным, однако. Это только дает критерий для обнаружения «границы» между областями, плотно расположенными с точками, и областями, менее плотными с точками. Нам все еще нужно сгруппировать точки в пряди.

На вашей картинке есть функция, которая показывает, что это не просто. В правом нижнем углу вашей фотографии есть относительно большая область с большим количеством случайных точек. Эти паразитные точки сами по себе примерно равномерно распределены, поэтому, если бы мы удалили все точки в пряди вокруг нее (и все остальные точки), мы могли бы ожидать, что любой алгоритм обнаружения нитей пометит этот набор паразитных точек как цепь! Поэтому мы должны быть осторожны при создании наших кластеров.

Идея может заключаться в следующем. Мы собираемся построить график для этих точек, где вершины - это точки, а ребра означают, что две точки имеют одинаковую плотность. Для каждого пункта мы проверяем критерий выше. Если он проверяется, мы соединяем X ребром со всеми точками в C. Если он не проверяется, мы не добавляем ребро и помечаем X как «отклоненный». Сделав это для каждой точки, мы рассмотрим набор связанных компонентов, Они должны состоять из одного (в случае вашей картинки, но в других наборах данных может быть несколько) связанного компонента, состоящего из всех точек в прядях, плюс (потенциально много) больше компонентов, состоящих из одних паразитных точек и этих «паразитных прядей». Однако у этих блуждающих нитей есть точки, помеченные как «блуждающие», поэтому вы можете просто игнорировать любой компонент, содержащий точку, помеченную как «блуждающую».

Опасность этой идеи заключается в том, что у вас может быть свойство, при котором плотность нити постепенно снижается по мере движения вдоль нити, пока плотность не станет настолько низкой, что это будет просто набор отклоняющихся точек. Поскольку наш критерий «локальный», он может не обнаружить это и пометить эти случайные точки как часть жилы. Я не уверен, будет ли это проблемой: я предполагаю, что большинство случайных точек должно быть поймано критерием, так как изменения плотности кажутся вам довольно резкими.

Если эта проблема действительно возникает, вы можете попробовать альтернативу, просто взяв подключенные компоненты. Для каждой точки X мы вычисляем расстояние до ближайшего соседа D (X). Мы начинаем с точки с минимальным D (X) и выполняем BFS (или DFS , порядок не имеет значения). Мы добавляем любую точку Y, у которой D (Y) не намного больше, чем D (X) (по настраиваемому коэффициенту), с которого мы начали. Если мы сталкиваемся с точкой Y, которая имеет слишком большой D (Y), мы удаляем ребро (X, Y), помечаем Y как «отклоненный» и действуем так, как будто мы никогда не посещали Y в нашей BFS. Если настроено правильно, это должно предотвратить проблему, которую я описал выше.

Альтернативная идея для решения этой проблемы действует немного более локально: вы можете сделать BFS и отслеживать самый низкий D (X) (я использую D (X) как меру плотности вокруг точки), встречающийся в большинстве случаев, скажем, 10 BFS-шаги раньше, и если мы встречаемся с Y, у которого D (Y) намного больше, чем это D (X), мы делаем то же самое, что и другое (потенциальное) решение, которое я предложил.

В качестве отказа от ответственности: все идеи, изложенные выше, я только что сразу придумал, я не знаю, была ли эта конкретная проблема изучена ранее, поэтому я, возможно, просто несу чушь. Просто попробуйте идеи (будь то мои идеи или ваши собственные), которые звучат для вас разумно, и выясните, действительно ли они работают, и только тогда сосредоточьтесь на их эффективной реализации.

Алекс тен Бринк
источник
2

Используя модульную декомпозицию, вы можете создать дерево, которое будет содержать все частицы в виде листьев, а верхние узлы будут кластеризовать их. На основе этого дерева вы можете определить меры, которые применяются к каждому его узлу, от корня до листьев вниз. Вы прекращаете этот обход вниз, когда измерения достигают определенных пользователем порогов. Одним из таких измерений может быть плотность выпуклой оболочки всех частиц в скоплении.

SpaceTrucker
источник
1

Я думаю, что вы после алгоритма кластеризации машинного обучения.

На этой странице из набора инструментов Python SciKit Learn есть картинки, которые показывают, что алгоритм DBSCAN (Википедия) может быть тем, что вы ищете. Это кажется идеальным, поскольку его входным параметром является размер окрестности, в то время как большинству других алгоритмов кластеризации требуется количество кластеров, которое вы не знали бы заранее.

«Алгоритм на основе плотности для обнаружения кластеров в больших пространственных базах данных с шумом», Эстер М., Х.Р. Кригель, Дж. Сандер и Х. Сюй, в материалах 2-й Международной конференции по обнаружению знаний и интеллектуальному анализу данных, Портленд, Орегон , AAAI Press, стр. 226–231. 1996

Том
источник
0

Я думал об этой проблеме. Я не специалист по физике, так что терпите меня.

Кажется, что это не расстояние между частицами, которое учитывает сгустки. Это то, перекрываются ли гравитационные поля.

Возьмите частицу P и определите, какие другие частицы имеют перекрывающиеся гравитационные поля.

Затем возьмите один из них и сделайте то же самое. Ваша цель не в том, чтобы найти все частицы в комке, а в том, чтобы найти его границы.

Повторяйте это, пока все комки не найдены.

Теперь вернитесь и определите массу глыб. У вас будут уничтожены случайные частицы, и вы можете использовать границы скопления, чтобы найти массу.

Я не уверен, поможет ли это, но это все, о чем я мог думать.

Джо Маккей
источник
Что такое гравитационное поле ?
Дэвид Коуден
0

В конце каждого временного шага вы можете преобразовать данные в график, вычислить минимальное остовное дерево и затем начать удалять ребра, которые превышают определенный порог. Это должно дать вам сгустки и простой способ перечисления частиц в каждом сгустке.

Джеймс
источник