Algoritmo per trovare la massa aggregata di "Granola Bar" -Come strutture?


19

Sono un ricercatore di scienze planetarie e un progetto a cui sto lavorando sono le simulazioni N- body degli anelli di Saturno. L'obiettivo di questo studio particolare è quello di osservare come le particelle si aggregano insieme sotto la loro stessa gravità e misurare la massa aggregata dei grumi rispetto alla velocità media di tutte le particelle nella cellula. Stiamo cercando di capire se questo può spiegare alcune osservazioni fatte dall'astronave Cassini durante il solstizio d'estate di Saturno, quando furono viste grandi strutture che proiettavano ombre sugli anelli quasi spigolosi. Di seguito è riportato uno screenshot di come appare un determinato timestep. (Ogni particella ha un diametro di 2 m e la cella di simulazione stessa ha un diametro di circa 700 m.)

Cella del corpo _N_ di una simulazione degli anelli di Saturno con particelle mostrate come minuscole sfere ombreggiate su uno sfondo nero.

Il codice che sto usando sputa già la velocità media ad ogni intervallo di tempo. Quello che devo fare è capire un modo per determinare la massa di particelle nei grumi e NON le particelle vaganti tra di loro. Conosco la posizione, la massa, la dimensione di ogni particella, ecc., Ma non so facilmente che, diciamo, le particelle 30.000-40.000 insieme a 102.000-105.000 costituiscono un filone che per l'occhio umano è ovvio.

Quindi, l'algoritmo che devo scrivere dovrebbe essere un codice con il minor numero possibile di parametri immessi dall'utente (per replicabilità e obiettività) che attraverserebbe tutte le posizioni delle particelle, capire quali particelle appartengono ai grumi e quindi calcolare il massa. Sarebbe bello se potesse farlo per "ogni" gruppo / filo al contrario di tutto ciò che si trova sopra la cella, ma non penso di averne effettivamente bisogno per separarli.

L'unica cosa a cui stavo pensando era fare una sorta di calcolo della distanza N 2 in cui avrei calcolato la distanza tra ogni particella e se, diciamo, le 100 particelle più vicine fossero entro una certa distanza, allora quella particella sarebbe considerata parte di un grappolo. Ma questo sembra piuttosto sciatto e speravo che voi CS e programmatori potreste conoscere una soluzione più elegante?


Modificato con la mia soluzione: quello che ho fatto è stato quello di adottare una sorta di approccio più vicino / cluster e fare prima l'implementazione di N 2 quick-n-dirty . Quindi, prendi ogni particella, calcola la distanza da tutte le altre particelle e la soglia per in un cluster o no era se ci fossero N particelle entro la distanza d (due parametri che devono essere impostati a priori , sfortunatamente, ma come è stato detto da alcuni risposte / commenti, non avevo intenzione di cavarmela senza averne qualcuno).

L'ho quindi accelerato non ordinando le distanze ma semplicemente facendo una ricerca nell'ordine N e incrementando un contatore per le particelle all'interno di d , e questo ha velocizzato le cose di un fattore 6. Poi ho aggiunto uno "stupido albero del programmatore" (perché lo so quasi nulla sui codici degli alberi). Divido la cella simulazione in un determinato numero di griglie (migliori risultati quando dimensione della griglia ≈7 d ) se le linee principali della griglia su con la cella, di una griglia è bilanciata da metà in x ed y , e le altre due sono compensati da 1/4 in ± x e ± y . Il codice quindi divide le particelle nelle griglie, quindi ogni particella N deve solo calcolare le distanze rispetto alle altre particelle in quella cella.

Teoricamente, se questo fosse un vero albero, dovrei ottenere l'ordine N * log ( N ) invece delle N 2 velocità. Sono arrivato a metà strada tra i due, dove per un sottoinsieme di 50.000 particelle ho ottenuto un aumento di velocità di 17x, e per una cella di 150.000 particelle, ho ottenuto un aumento di 38x di velocità. 12 secondi per il primo, 53 secondi per il secondo, 460 secondi per una cella da 500.000 particelle. Queste sono velocità comparabili a quanto tempo impiega il codice per eseguire il timestep di simulazione 1 in avanti, quindi è ragionevole a questo punto. Oh - ed è completamente thread, quindi ci vorranno tutti i processori che posso lanciarci.


3
Non sono particolarmente informato su questo argomento, quindi posso fornire poco in termini di assistenza me stesso, ma hai letto l' articolo di Wikipedia sull'analisi dei cluster ? Sembra essere un campo di studio molto attivo.
Cole Campbell,

Sono diffidente nei confronti di un codice cluster, almeno qualcosa come DBSCAN, perché penso che "seguirebbe" alcuni dei sottili filoni che conosco visivamente non fanno parte dei cluster, ma potrebbe essere algoritmicamente. Ho esperienza con i codici di tipo DBSCAN da quando lo uso per gli altri miei lavori, studiando i crateri.
Stuart Robbins,

1
Qualsiasi codice che identifichi fili come questo verrebbe quasi certamente con una sorta di impostazione di "sensibilità".
Robert Harvey,

2
Concordato. La vera difficoltà qui è che "ammasso" non è un termine ben definito. Alla fine della giornata dovrai scegliere una sorta di algoritmo di analisi dei cluster (che, in realtà, è già la tua soluzione proposta), forse combinato con una sorta di passaggio di riduzione del rumore.
Cole Campbell,

2
potrebbe essere utile se disegni sulla tua foto quello che pensi sia un gruppo valido (e forse non valido)
jk.

Risposte:


3

Il mio primo suggerimento è di tagliare il problema in due problemi: in primo luogo, capire cosa vuoi e poi capire come ottenere in modo efficiente ciò che vuoi. Non puoi ottenere in modo efficiente qualcosa che non hai ancora definito. Metterò alcune idee in questa risposta che potrebbero aiutarti a trovare questa definizione. Ti suggerisco di implementare in modo inefficiente le idee che ti piacciono per prime, applicarle a pochi set di dati non troppo grandi, valutare manualmente i risultati, adattare la tua definizione e ripetere (eventualmente facendo un'altra domanda qui), fino a quando non sei soddisfatto la tua definizione. Successivamente, ti suggerisco di porre un'altra domanda su come calcolare in modo efficiente il risultato della tua definizione (se hai ancora bisogno di aiuto).

Quindi, vediamo cosa corrisponderebbe alla nostra idea intuitiva di un "filo". I tuoi fili sembrano consistere in punti distribuiti in modo approssimativamente uniforme, anche se dovresti verificarlo creando un'immagine ingrandita (del set di dati originale) - la risoluzione della tua immagine è troppo bassa per dire con certezza che i punti sono davvero distribuiti in modo approssimativamente uniforme . Presumo che siano per questa risposta.

Un'idea iniziale potrebbe essere quella di guardare il vicino più vicino di ogni punto. Selezioniamo un punto X, chiamiamo il vicino Y più vicino e impostiamo D come distanza tra X e Y. Osserviamo quindi il cerchio C attorno a X con raggio D * A, dove A è un parametro di ottimizzazione, diciamo A = 3. Se X fa parte di un filo, ci aspettiamo che per ogni punto Z in C, la distanza da Z al suo vicino più vicino W sia circa la stessa di D. Se è significativamente più breve, dire più di A (o forse qualche altro parametro B) allora X sembra essere vicino a punti molto più vicini tra loro che a X, quindi X probabilmente non fa parte di un filo.

Questo criterio non è completo tuttavia. Fornisce solo un criterio per rilevare un "confine" tra aree piene di punti e aree meno dense di punti. Dobbiamo ancora raggruppare i punti in trefoli.

C'è una caratteristica nella tua foto che mostra che questo non è semplice. Nell'angolo in basso a destra della tua foto, c'è un'area relativamente grande con molti punti randagi. Questi punti randagi sono essi stessi distribuiti in modo approssimativamente uniforme, quindi se dovessimo rimuovere tutti i punti del filo attorno ad esso (e tutti gli altri punti), ci aspetteremmo che qualsiasi algoritmo di rilevamento del filo marcasse questo insieme di punti randagi come un filo! Pertanto, dobbiamo fare attenzione quando creiamo i nostri cluster.

Un'idea potrebbe essere quella di fare quanto segue. Faremo un grafico su questi punti, dove i vertici sono i punti e gli spigoli indicano che due punti hanno una densità simile. Per ogni punto, controlliamo il criterio sopra. Se si verifica, connettiamo X con un bordo a tutti i punti in C. In caso contrario, non aggiungiamo alcun bordo e contrassegniamo X come "randagio". Dopo aver fatto questo per ogni punto, consideriamo l'insieme dei componenti collegati. Questi dovrebbero essere costituiti da un singolo componente (nel caso della tua immagine, ma altri set di dati potrebbero avere più) un componente connesso costituito da tutti i punti nei trefoli, più (potenzialmente molti) più componenti costituiti da singoli punti randagi e questi "filamenti vaganti". Tuttavia, questi fili vaganti hanno punti contrassegnati come "vaganti", quindi puoi semplicemente ignorare qualsiasi componente contenente un punto che è stato marcato come "vagante".

Un pericolo di questa idea è che potresti avere una caratteristica in cui la densità di un filo si abbassa progressivamente mentre ti muovi lungo il filo, fino a quando la densità è così bassa che è solo un insieme di punti vaganti. Poiché il nostro criterio è "locale", potrebbe non essere possibile rilevare questo e contrassegnare questi punti vaganti come parte del filo. Non sono sicuro se questo sarà un problema: immagino che la maggior parte dei punti vaganti dovrebbe essere colta dal criterio, poiché i cambiamenti di densità sembrano piuttosto bruschi nella tua foto.

Se si verifica questo problema, è possibile provare un'alternativa al solo prendere i componenti collegati. Per ogni punto X, calcoliamo la distanza dal vicino più vicino D (X). Partiamo dal punto con D minima (X) ed eseguiamo un BFS (o DFS , l'ordine non ha importanza). Aggiungiamo qualsiasi punto Y la cui D (Y) non è molto più grande della D (X) (per un fattore sintonizzabile) con cui abbiamo iniziato. Se incontriamo un punto Y con D (Y) troppo grande, rimuoviamo il bordo (X, Y), contrassegniamo Y come "randagio" e ci comportiamo come se non avessimo mai visitato Y nel nostro BFS. Se ottimizzato, questo dovrebbe prevenire il problema che ho descritto sopra.

Un'idea alternativa per risolvere questo problema agisce un po 'più localmente: potresti fare un BFS e tenere traccia della D (X) più bassa (io uso D (X) come misura della densità attorno ad un punto) riscontrata al massimo 10 Passaggi BFS prima e se incontriamo una Y che ha D (Y) molto più grande di questa D (X), facciamo la stessa dell'altra (potenziale) soluzione che ho offerto.

Come disclaimer: tutte le idee sopra che ho pensato sul posto proprio ora, non so davvero se questo particolare problema è stato studiato prima, quindi potrei solo far nascere sciocchezze. Prova le idee (che siano mie o tue) che ti sembrano sensate e scopri se funzionano davvero, e solo allora concentrati sull'attuazione efficiente.


2

Usando la decomposizione modulare è possibile creare un albero che conterrà tutte le particelle mentre foglie e nodi superiori le raggrupperanno. Sulla base di quell'albero è possibile definire le misure che vengono applicate a ciascun nodo dalla radice alle foglie verso il basso. Si interrompe questo attraversamento verso il basso quando le misurazioni raggiungono soglie definite dall'utente. Una di queste misure può essere la densità dello scafo convesso di tutte le particelle in un cluster.


1

Penso che tu stia cercando un algoritmo di clustering di machine learning.

Questa pagina dal toolkit Python SciKit Learn contiene immagini che suggeriscono che l' algoritmo DBSCAN (Wikipedia) potrebbe essere quello che stai cercando. Sembra ideale in quanto il parametro di input è la dimensione del vicinato, mentre la maggior parte degli altri algoritmi di clustering vuole il numero di cluster, che non si saprebbero in anticipo.

"Un algoritmo basato sulla densità per scoprire cluster in grandi database spaziali con rumore" Ester, M., HP Kriegel, J. Sander e X. Xu, in Atti della 2a Conferenza internazionale sulla scoperta della conoscenza e l'estrazione dei dati, Portland, OR , AAAI Press, pagg. 226–231. 1996


0

Ho pensato a questo problema. Non sono un esperto di fisica, quindi abbi pazienza.

Sembra che non sia la distanza tra le particelle che conta per determinare i grumi. Indica se i campi di gravità si sovrappongono o meno.

Prendi una particella P e determina quali altre particelle hanno campi di gravità sovrapposti.

Quindi prendi uno di quelli e fai la stessa cosa. Il tuo obiettivo non è quello di trovare tutte le particelle nel gruppo, ma di trovare i suoi confini.

Ripetere l'operazione fino a quando non vengono trovati tutti i grumi.

Ora torna indietro e determina la massa dei grumi. Avrai eliminato le particelle vaganti e potrai usare i confini del gruppo per trovare la massa.

Non sono sicuro che questo aiuti, ma è tutto ciò che mi viene in mente.


Che cos'è un campo di gravità ?
David Cowden,

0

Alla fine di ogni timestep, è possibile convertire i dati in un grafico, calcolare l'albero di spanning minimo e quindi iniziare a rimuovere i bordi che superano una determinata soglia. Questo dovrebbe darti dei grumi e un modo semplice per enumerare le particelle in ciascun grumo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.