seguidores para likes interaccion hay grupos grupo ganar aumentar algorithm geocoding cluster-analysis data-mining markerclusterer

algorithm - para - ¿Cómo puedo encontrar el centro de un grupo de puntos de datos?



hay grupos en instagram (14)

En astrofísica usamos el llamado "radio de media masa". Dada una distribución y su centro, el radio de media masa es el radio mínimo de un círculo que contiene la mitad de los puntos de su distribución.

Esta cantidad es una longitud característica de una distribución de puntos.

¡Si quieres que la casa del helicóptero sea donde los puntos están concentrados al máximo, es el punto que tiene el radio mínimo de media masa!

Mi algoritmo es el siguiente: para cada punto, calcula este radio de media masa centrando la distribución en el punto actual. El "hogar" del helicóptero será el punto con el radio mínimo de la mitad de la masa.

Lo he implementado y el centro computado es 42.149994 -88.133698 (que está en Chicago). También he usado el 0.2 de la masa total en vez del 0.5 (la mitad) generalmente usado en Astrofísica.

Este es mi algoritmo (en python) que encuentra el hogar del helicóptero:

import math import numpy def inside(points,center,radius): ids=(((points[:,0]-center[0])**2.+(points[:,1]-center[1])**2.)<=radius**2.) return points[ids] points = numpy.loadtxt(open(''points.txt''),comments=''#'') npoints=len(points) deltar=0.1 idcenter=None halfrmin=None for i in xrange(0,npoints): center=points[i] radius=0. stayHere=True while stayHere: radius=radius+deltar ninside=len(inside(points,center,radius)) #print ''point'',i,''r'',radius,''in'',ninside,''center'',center if(ninside>=npoints*0.2): if(halfrmin==None or radius<halfrmin): halfrmin=radius idcenter=i print ''point'',i,halfrmin,idcenter,points[idcenter] stayHere=False #print halfrmin,idcenter print points[idcenter]

Supongamos que he trazado la posición de un helicóptero todos los días durante el año pasado y se me ocurrió el siguiente mapa:

Cualquier persona que vea esto podría decirme que este helicóptero tiene su base en Chicago.

¿Cómo puedo encontrar el mismo resultado en el código?

Estoy buscando algo como esto:

$geoCodeArray = array([GET=http://pastebin.com/grVsbgL9]); function findHome($geoCodeArray) { // magic return $geoCode; }

En última instancia generando algo como esto:

ACTUALIZACIÓN: Dataset de muestra

Aquí hay un mapa con un conjunto de datos de muestra: http://batchgeo.com/map/c3676fe29985f00e1605cd4f86920179

Aquí hay un pastebin de 150 geocódigos: http://pastebin.com/grVsbgL9

Lo anterior contiene 150 geocódigos. Los primeros 50 están en algunos grupos cerca de Chicago. El resto está disperso por todo el país, incluidos algunos pequeños grupos en Nueva York, Los Ángeles y San Francisco.

Tengo alrededor de un millón de (seriamente) conjuntos de datos como este que necesitaré para iterar e identificar el "hogar" más probable. Tu ayuda es muy apreciada.

ACTUALIZACIÓN 2: Avión cambiado a helicóptero

El concepto de avión atraía demasiada atención hacia los aeropuertos físicos. Las coordenadas pueden estar en cualquier parte del mundo, no solo en los aeropuertos. Supongamos que es un súper helicóptero no limitado por la física, el combustible o cualquier otra cosa. Puede aterrizar donde quiera. ;)


Encuentra el punto con el mayor estimado de densidad .

Debería ser bastante sencillo. Use un radio de núcleo que cubra aproximadamente un gran aeropuerto de diámetro. Un kernel 2D gaussiano o Epanechnikov debería estar bien.

http://en.wikipedia.org/wiki/Multivariate_kernel_density_estimation

Esto es similar a calcular un Mapa de Heap: http://en.wikipedia.org/wiki/Heat_map y luego encontrar el lugar más brillante allí. Excepto que calcula el brillo de inmediato.

Por diversión, leí una muestra del 1% de Geocoordinadas de DBpedia (es decir, Wikipedia) en ELKI, la proyecté en el espacio 3D y habilité la superposición de estimación de densidad (oculta en el menú de diagrama de dispersión de los visualizadores). Puedes ver que hay un punto de acceso en Europa y, en menor medida, en los EE. UU. El punto de acceso en Europa es Polonia, creo. La última vez que lo comprobé, aparentemente alguien había creado un artículo de Wikipedia con geocoordinados para casi cualquier ciudad de Polonia. Desafortunadamente, el visualizador ELKI no le permite acercarse, girar o reducir el ancho de banda del kernel para encontrar visualmente el punto más denso. Pero es sencillo implementarlo usted mismo; Es probable que tampoco necesite ir al espacio 3D, sino que solo puede usar latitudes y longitudes.

La estimación de la densidad del núcleo debe estar disponible en toneladas de aplicaciones. El que está en R es probablemente mucho más poderoso. Hace poco descubrí este mapa de calor en ELKI, así que supe cómo acceder a él rápidamente. Consulte, por ejemplo, http://stat.ethz.ch/R-manual/R-devel/library/stats/html/density.html para ver una función R relacionada.

En tus datos, en R, prueba por ejemplo:

library(kernSmooth) smoothScatter(data, nbin=512, bandwidth=c(.25,.25))

Esto debería mostrar una fuerte preferencia por Chicago.

library(kernSmooth) dens=bkde2D(data, gridsize=c(512, 512), bandwidth=c(.25,.25)) contour(dens$x1, dens$x2, dens$fhat) maxpos = which(dens$fhat == max(dens$fhat), arr.ind=TRUE) c(dens$x1[maxpos[1]], dens$x2[maxpos[2]])

cede [1] 42.14697 -88.09508 , que está a menos de 10 millas del aeropuerto de Chicago.

Para obtener mejores coordenadas prueba:

  • volver a ejecutar en un área de 20x20 millas alrededor de las coordenadas estimadas
  • un KDE sin contenedor en esa área
  • mejor selección de ancho de banda con dpik
  • mayor resolución de cuadrícula

Esto se puede resolver encontrando una superficie de peligro . Ver la Fórmula de Rossmo .

Este es el problema de los depredadores . Dado un conjunto de cadáveres ubicados geográficamente, ¿dónde está la guarida del depredador? La fórmula de Rossmo resuelve este problema.


La siguiente solución funciona incluso si los puntos están dispersos por toda la Tierra, al convertir la latitud y la longitud en coordenadas cartesianas. Hace un tipo de KDE (estimación de la densidad del kernel), pero en un primer paso la suma de los kernels se evalúa solo en los puntos de datos. El núcleo debe ser elegido para adaptarse al problema. En el siguiente código, es lo que podría llamar en broma / presuntuosamente un Trossian, es decir, 2-d² / h² para d≤h y h² / d² para d> h (donde d es la distancia euclidiana yh es el "ancho de banda" $global_kernel_radius ), pero también podría ser un Gaussian (e -d² / 2h² ), un kernel Epanechnikov (1-d² / h² para d <h, 0 de lo contrario), u otro kernel. Un segundo pase opcional refina la búsqueda localmente, ya sea sumando un kernel independiente en una grilla local, o calculando el centroide, en ambos casos en un entorno definido por $local_grid_radius .

En esencia , cada punto suma todos los puntos que tiene alrededor (incluido él mismo), ponderándolos más si están más cerca (por la curva de campana), y también $w_arr matriz de peso opcional $w_arr . El ganador es el punto con la suma máxima. Una vez que se ha encontrado al ganador, el "hogar" que estamos buscando se puede encontrar repitiendo el mismo proceso localmente alrededor del ganador (usando otra curva de campana), o puede estimarse como el "centro de masa" de todos los puntos dentro de un radio dado del ganador, donde el radio puede ser cero.

El algoritmo debe adaptarse al problema seleccionando los núcleos adecuados, eligiendo cómo refinar la búsqueda localmente y ajustando los parámetros. Para el conjunto de datos de ejemplo, el kernel Trossian para la primera pasada y el kernel Epanechnikov para la segunda pasada, con los 3 radios configurados en 30 mi y un paso de 1 mil en la cuadrícula podrían ser un buen punto de inicio, pero solo si los dos subgrupos Los grupos de Chicago deben ser vistos como un grupo grande. De lo contrario se deben elegir radios más pequeños.

function find_home($lat_arr, $lng_arr, $global_kernel_radius, $local_kernel_radius, $local_grid_radius, // 0 for no 2nd pass $local_grid_step, // 0 for centroid $units=''mi'', $w_arr=null) { // for lat,lng <-> x,y,z see http://en.wikipedia.org/wiki/Geodetic_datum // for K and h see http://en.wikipedia.org/wiki/Kernel_density_estimation switch (strtolower($units)) { /* */case ''nm'' : /*or*/case ''nmi'': $m_divisor = 1852; break;case ''mi'': $m_divisor = 1609.344; break;case ''km'': $m_divisor = 1000; break;case ''m'': $m_divisor = 1; break;default: return false; } $a = 6378137 / $m_divisor; // Earth semi-major axis (WGS84) $e2 = 6.69437999014E-3; // First eccentricity squared (WGS84) $lat_lng_count = count($lat_arr); if ( !$w_arr) { $w_arr = array_fill(0, $lat_lng_count, 1.0); } $x_arr = array(); $y_arr = array(); $z_arr = array(); $rad = M_PI / 180; $one_e2 = 1 - $e2; for ($i = 0; $i < $lat_lng_count; $i++) { $lat = $lat_arr[$i]; $lng = $lng_arr[$i]; $sin_lat = sin($lat * $rad); $sin_lng = sin($lng * $rad); $cos_lat = cos($lat * $rad); $cos_lng = cos($lng * $rad); // height = 0 (!) $N = $a / sqrt(1 - $e2 * $sin_lat * $sin_lat); $x_arr[$i] = $N * $cos_lat * $cos_lng; $y_arr[$i] = $N * $cos_lat * $sin_lng; $z_arr[$i] = $N * $one_e2 * $sin_lat; } $h = $global_kernel_radius; $h2 = $h * $h; $max_K_sum = -1; $max_K_sum_idx = -1; for ($i = 0; $i < $lat_lng_count; $i++) { $xi = $x_arr[$i]; $yi = $y_arr[$i]; $zi = $z_arr[$i]; $K_sum = 0; for ($j = 0; $j < $lat_lng_count; $j++) { $dx = $xi - $x_arr[$j]; $dy = $yi - $y_arr[$j]; $dz = $zi - $z_arr[$j]; $d2 = $dx * $dx + $dy * $dy + $dz * $dz; $K_sum += $w_arr[$j] * ($d2 <= $h2 ? (2 - $d2 / $h2) : $h2 / $d2); // Trossian ;-) // $K_sum += $w_arr[$j] * exp(-0.5 * $d2 / $h2); // Gaussian } if ($max_K_sum < $K_sum) { $max_K_sum = $K_sum; $max_K_sum_i = $i; } } $winner_x = $x_arr [$max_K_sum_i]; $winner_y = $y_arr [$max_K_sum_i]; $winner_z = $z_arr [$max_K_sum_i]; $winner_lat = $lat_arr[$max_K_sum_i]; $winner_lng = $lng_arr[$max_K_sum_i]; $sin_winner_lat = sin($winner_lat * $rad); $cos_winner_lat = cos($winner_lat * $rad); $sin_winner_lng = sin($winner_lng * $rad); $cos_winner_lng = cos($winner_lng * $rad); $east_x = -$local_grid_step * $sin_winner_lng; $east_y = $local_grid_step * $cos_winner_lng; $east_z = 0; $north_x = -$local_grid_step * $sin_winner_lat * $cos_winner_lng; $north_y = -$local_grid_step * $sin_winner_lat * $sin_winner_lng; $north_z = $local_grid_step * $cos_winner_lat; if ($local_grid_radius > 0 && $local_grid_step > 0) { $r = intval($local_grid_radius / $local_grid_step); $r2 = $r * $r; $h = $local_kernel_radius; $h2 = $h * $h; $max_L_sum = -1; $max_L_sum_idx = -1; for ($i = -$r; $i <= $r; $i++) { $winner_east_x = $winner_x + $i * $east_x; $winner_east_y = $winner_y + $i * $east_y; $winner_east_z = $winner_z + $i * $east_z; $j_max = intval(sqrt($r2 - $i * $i)); for ($j = -$j_max; $j <= $j_max; $j++) { $x = $winner_east_x + $j * $north_x; $y = $winner_east_y + $j * $north_y; $z = $winner_east_z + $j * $north_z; $L_sum = 0; for ($k = 0; $k < $lat_lng_count; $k++) { $dx = $x - $x_arr[$k]; $dy = $y - $y_arr[$k]; $dz = $z - $z_arr[$k]; $d2 = $dx * $dx + $dy * $dy + $dz * $dz; if ($d2 < $h2) { $L_sum += $w_arr[$k] * ($h2 - $d2); // Epanechnikov } } if ($max_L_sum < $L_sum) { $max_L_sum = $L_sum; $max_L_sum_i = $i; $max_L_sum_j = $j; } } } $x = $winner_x + $max_L_sum_i * $east_x + $max_L_sum_j * $north_x; $y = $winner_y + $max_L_sum_i * $east_y + $max_L_sum_j * $north_y; $z = $winner_z + $max_L_sum_i * $east_z + $max_L_sum_j * $north_z; } else if ($local_grid_radius > 0) { $r = $local_grid_radius; $r2 = $r * $r; $wx_sum = 0; $wy_sum = 0; $wz_sum = 0; $w_sum = 0; for ($k = 0; $k < $lat_lng_count; $k++) { $xk = $x_arr[$k]; $yk = $y_arr[$k]; $zk = $z_arr[$k]; $dx = $winner_x - $xk; $dy = $winner_y - $yk; $dz = $winner_z - $zk; $d2 = $dx * $dx + $dy * $dy + $dz * $dz; if ($d2 <= $r2) { $wk = $w_arr[$k]; $wx_sum += $wk * $xk; $wy_sum += $wk * $yk; $wz_sum += $wk * $zk; $w_sum += $wk; } } $x = $wx_sum / $w_sum; $y = $wy_sum / $w_sum; $z = $wz_sum / $w_sum; $max_L_sum_i = false; $max_L_sum_j = false; } else { return array($winner_lat, $winner_lng, $max_K_sum_i, false, false); } $deg = 180 / M_PI; $a2 = $a * $a; $e4 = $e2 * $e2; $p = sqrt($x * $x + $y * $y); $zeta = (1 - $e2) * $z * $z / $a2; $rho = ($p * $p / $a2 + $zeta - $e4) / 6; $rho3 = $rho * $rho * $rho; $s = $e4 * $zeta * $p * $p / (4 * $a2); $t = pow($s + $rho3 + sqrt($s * ($s + 2 * $rho3)), 1 / 3); $u = $rho + $t + $rho * $rho / $t; $v = sqrt($u * $u + $e4 * $zeta); $w = $e2 * ($u + $v - $zeta) / (2 * $v); $k = 1 + $e2 * (sqrt($u + $v + $w * $w) + $w) / ($u + $v); $lat = atan($k * $z / $p) * $deg; $lng = atan2($y, $x) * $deg; return array($lat, $lng, $max_K_sum_i, $max_L_sum_i, $max_L_sum_j); }

El hecho de que las distancias sean euclidianas y no de gran círculo debería tener efectos insignificantes para la tarea en cuestión. Calcular las distancias del círculo máximo sería mucho más engorroso y haría que el peso de los puntos muy lejanos sea significativamente menor, pero estos puntos ya tienen un peso muy bajo. En principio, un kernel diferente podría lograr el mismo efecto. Los núcleos que tienen un punto de corte completo más allá de cierta distancia, como el núcleo Epanechnikov, no tienen este problema en absoluto (en la práctica).

La conversión entre lat, lng y x, y, z para el dato WGS84 se da exactamente (aunque sin garantía de estabilidad numérica) más como referencia que por una necesidad real. Si se debe tener en cuenta la altura o si se necesita una conversión de retroceso más rápida, consulte el artículo de Wikipedia .

El kernel de Epanechnikov, además de ser "más local" que los núcleos de Gauss y Trossian, tiene la ventaja de ser el más rápido para el segundo ciclo, que es O (ng), donde g es el número de puntos de la cuadrícula local y puede También se empleará en el primer bucle, que es O (n²), si n es grande.


Puede adaptar fácilmente la fórmula de Rossmo, citada por Tyler Durden a su caso, con algunas notas simples:

La formula :

Esta fórmula proporciona algo parecido a la probabilidad de presencia de la operación base para un depredador o un asesino en serie. En tu caso, podría dar la probabilidad de que una base esté en un cierto punto. Más adelante explicaré cómo usarlo. U puede escribirlo de esta manera:

Proba (base en el punto A) = Suma {en todos los puntos} (Phi / (dist ^ f) + (1-Phi) (B * (gf)) / (2B-dist) ^ g)

Usando la distancia euclidiana

Desea una distancia euclidiana y no la de Manhattan porque un avión o un helicóptero no está obligado a la carretera / calles. Por lo tanto, usar la distancia euclidiana es la forma correcta, si está siguiendo un avión y no un asesino en serie. Entonces, "dist" en la fórmula es la distancia euclidiana entre el punto de prueba y el punto considerado

Tomando la variable razonable B

La variable B se utilizó para representar la regla "un asesino razonablemente inteligente no matará a su vecino". En su caso, el testamento también se aplicó porque nadie usa un avión / roflcopter para llegar a la siguiente esquina. Podemos suponer que el viaje mínimo es, por ejemplo, de 10 km o algo razonable cuando se aplica a su caso.

Factor exponencial f

El factor f se usa para agregar un peso a la distancia. Por ejemplo, si todas las manchas se encuentran en un área pequeña, podría desear un gran factor f porque la probabilidad de que el aeropuerto / base / HQ disminuya rápidamente si todos sus puntos de datos están en el mismo sector. g funciona de manera similar, permite elegir el tamaño de la "base no es probable que esté justo al lado del lugar"

Factor phi:

Nuevamente, este factor debe determinarse utilizando su conocimiento del problema. Permite elegir el factor más preciso entre "la base está cerca de los puntos" y "no usaré el plano para hacer 5 m" si, por ejemplo, cree que la segunda es casi irrelevante, puede configurar Phi en 0.95 (0<Phi<1)Si ambos son interesantes phi estarán alrededor de 0.5

Cómo implementarlo como algo útil:

Primero, debe dividir su mapa en cuadraditos: entrelazar el mapa (como invisal) (cuanto más pequeños sean los cuadrados, más preciso será el resultado (en general)) y luego usar la fórmula para encontrar la ubicación más probable. De hecho, la malla es solo una matriz con todas las ubicaciones posibles. (Si quieres ser preciso, aumentas la cantidad de puntos posibles, pero requerirá más tiempo de computación y PhP no es muy conocido por su increíble velocidad)

Algoritmo

//define all the factors you need(B , f , g , phi) for(i=0..mesh_size) // computing the probability of presence for each square of the mesh { P(i)=0; geocode squarePosition;//GeoCode of the square''s center for(j=0..geocodearray_size)//sum on all the known spots { dist=Distance(geocodearray[j],squarePosition);//small function returning distance between two geocodes P(i)+=(Phi/pow(dist,f))+(1-Phi)*pow(B,g-f)/pow(2B-dist,g); } } return geocode corresponding to max(P(i))

Espero que te ayude


Puede usar DBSCAN para esa tarea.

DBSCAN es un clúster basado en densidad con una noción de ruido. Necesitas dos parámetros:

Primero, la cantidad de puntos que un grupo debe tener como mínimo "minpoints" mínimos "minpoints" . Y segundo, un parámetro de barrio llamado "epsilon" que establece un umbral de distancia a los puntos circundantes que deben incluirse en el clúster.

Todo el algoritmo funciona así:

  1. Comience con un punto arbitrario en su conjunto que aún no se haya visitado
  2. Recuperar puntos del vecindario epsilon marcar todos como visitados
    1. Si ha encontrado suficientes puntos en este vecindario (> parámetro de minpoints), inicia un nuevo grupo y asigna esos puntos. Ahora recurse en el paso 2 nuevamente para cada punto de este clúster.
    2. si no tiene, declare este punto como ruido
  3. vuelve a repetir hasta que hayas visitado todos los puntos

Es realmente simple de implementar y hay muchos frameworks que soportan este algoritmo. Para encontrar la media de su grupo, simplemente puede tomar la media de todos los puntos asignados de su vecindario.

Sin embargo, a diferencia del método que @TylerDurden propone, esto necesita una parametrización, por lo que debe encontrar algunos parámetros ajustados a mano que se ajusten a su problema.

En su caso, puede tratar de establecer los minpoints al 10% de su total de puntos si es probable que el avión permanezca el 10% del tiempo que rastrea en un aeropuerto. El parámetro de densidad epsilon depende de la resolución de su sensor geográfico y de la métrica de distancia que utiliza. Yo sugeriría la distancia más grande para los datos geográficos.


Todo lo que tengo en esta máquina es un viejo compilador, así que hice una versión ASCII de esto. "Dibuja" (en ASCII) un mapa: los puntos son puntos, X es donde está la fuente real, G es donde está la fuente adivinada. Si los dos se superponen, solo se muestra X

Ejemplos (DIFICULTAD 1.5 y 3 respectivamente):

Los puntos se generan seleccionando un punto aleatorio como fuente, luego distribuyendo puntos aleatoriamente, lo que hace que sea más probable que estén más cerca de la fuente.

DIFFICULTY es una constante de punto flotante que regula la generación de puntos inicial (cuanto más probable es que los puntos estén más cerca de la fuente), si es 1 o menos, el programa debe poder adivinar la fuente exacta o muy cerca. En 2.5, todavía debería ser bastante decente. Con 4+, comenzará a adivinar peor, pero creo que todavía adivina mejor de lo que lo haría un humano.

Podría optimizarse usando la búsqueda binaria sobre X, luego Y; esto empeoraría la suposición, pero sería mucho, mucho más rápido. O comenzando con bloques más grandes, luego dividiendo mejor el mejor bloque (o el mejor bloque y los 8 que lo rodean). Para un sistema de mayor resolución, uno de estos sería necesario. Sin embargo, este es un enfoque bastante ingenuo, pero parece funcionar bien en un sistema de 80x24. :RE

#include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> #define Y 24 #define X 80 #define DIFFICULTY 1 // Try different values... static int point[Y][X]; double dist(int x1, int y1, int x2, int y2) { return sqrt((y1 - y2)*(y1 - y2) + (x1 - x2)*(x1 - x2)); } main() { srand(time(0)); int y = rand()%Y; int x = rand()%X; // Generate points for (int i = 0; i < Y; i++) { for (int j = 0; j < X; j++) { double u = DIFFICULTY * pow(dist(x, y, j, i), 1.0 / DIFFICULTY); if ((int)u == 0) u = 1; point[i][j] = !(rand()%(int)u); } } // Find best source int maxX = -1; int maxY = -1; double maxScore = -1; for (int cy = 0; cy < Y; cy++) { for (int cx = 0; cx < X; cx++) { double score = 0; for (int i = 0; i < Y; i++) { for (int j = 0; j < X; j++) { if (point[i][j] == 1) { double d = dist(cx, cy, j, i); if (d == 0) d = 0.5; score += 1000 / d; } } } if (score > maxScore || maxScore == -1) { maxScore = score; maxX = cx; maxY = cy; } } } // Print out results for (int i = 0; i < Y; i++) { for (int j = 0; j < X; j++) { if (i == y && j == x) printf("X"); else if (i == maxY && j == maxX) printf("G"); else if (point[i][j] == 0) printf(" "); else if (point[i][j] == 1) printf("."); } } printf("Distance from real source: %f", dist(maxX, maxY, x, y)); scanf("%d", 0); }


Un modelo de mezcla simple parece funcionar bastante bien para este problema.

En general, para obtener un punto que minimiza la distancia a todos los otros puntos en un conjunto de datos, puede simplemente tomar la media. En este caso, desea buscar un punto que minimice la distancia desde un subconjunto de puntos concentrados. Si postula que un punto puede provenir del conjunto concentrado de puntos de interés o de un conjunto difuso de puntos de fondo, entonces se obtiene un modelo de mezcla.

He incluido algunos códigos Python a continuación. El área concentrada se modela mediante una distribución normal de alta precisión y el punto de fondo se modela mediante una distribución normal de baja precisión o una distribución uniforme sobre un cuadro delimitador en el conjunto de datos (hay una línea de código que puede comentarse cambiar entre estas opciones). Además, los modelos de mezcla pueden ser algo inestables, por lo que ejecutar el algoritmo EM varias veces con condiciones iniciales aleatorias y elegir la ejecución con la mayor probabilidad de registro da mejores resultados.

Si realmente está mirando aviones, entonces agregar algún tipo de dinámica dependiente del tiempo probablemente mejorará su capacidad de inferir inmensamente la base de operaciones.

También desconfiaría de la fórmula de Rossimo porque incluye algunas suposiciones bastante fuertes sobre la distribución de delitos.

#the dataset sdata=''''''41.892694,-87.670898 42.056048,-88.000488 41.941744,-88.000488 42.072361,-88.209229 42.091933,-87.982635 42.149994,-88.133698 42.171371,-88.286133 42.23241,-88.305359 42.196811,-88.099365 42.189689,-88.188629 42.17646,-88.173523 42.180531,-88.209229 42.18168,-88.187943 42.185496,-88.166656 42.170485,-88.150864 42.150634,-88.140564 42.156743,-88.123741 42.118555,-88.105545 42.121356,-88.112755 42.115499,-88.102112 42.119319,-88.112411 42.118046,-88.110695 42.117791,-88.109322 42.182189,-88.182449 42.194145,-88.183823 42.189057,-88.196182 42.186513,-88.200645 42.180917,-88.197899 42.178881,-88.192062 41.881656,-87.6297 41.875521,-87.6297 41.87872,-87.636566 41.872073,-87.62661 41.868239,-87.634506 41.86875,-87.624893 41.883065,-87.62352 41.881021,-87.619743 41.879998,-87.620087 41.8915,-87.633476 41.875163,-87.620773 41.879125,-87.62558 41.862763,-87.608757 41.858672,-87.607899 41.865192,-87.615795 41.87005,-87.62043 42.073061,-87.973022 42.317241,-88.187256 42.272546,-88.088379 42.244086,-87.890625 42.044512,-88.28064 39.754977,-86.154785 39.754977,-89.648437 41.043369,-85.12207 43.050074,-89.406738 43.082179,-87.912598 42.7281,-84.572754 39.974226,-83.056641 38.888093,-77.01416 39.923692,-75.168457 40.794318,-73.959961 40.877439,-73.146973 40.611086,-73.740234 40.627764,-73.234863 41.784881,-71.367187 42.371988,-70.993652 35.224587,-80.793457 36.753465,-76.069336 39.263361,-76.530762 25.737127,-80.222168 26.644083,-81.958008 30.50223,-87.275391 29.436309,-98.525391 30.217839,-97.844238 29.742023,-95.361328 31.500409,-97.163086 32.691688,-96.877441 32.691688,-97.404785 35.095754,-106.655273 33.425138,-112.104492 32.873244,-117.114258 33.973545,-118.256836 33.681497,-117.905273 33.622982,-117.734985 33.741828,-118.092041 33.64585,-117.861328 33.700707,-118.015137 33.801189,-118.251343 33.513132,-117.740479 32.777244,-117.235107 32.707939,-117.158203 32.703317,-117.268066 32.610821,-117.075806 34.419726,-119.701538 37.750358,-122.431641 37.50673,-122.387695 37.174817,-121.904297 37.157307,-122.321777 37.271492,-122.033386 37.435238,-122.217407 37.687794,-122.415161 37.542025,-122.299805 37.609506,-122.398682 37.544203,-122.0224 37.422151,-122.13501 37.395971,-122.080078 45.485651,-122.739258 47.719463,-122.255859 47.303913,-122.607422 45.176713,-122.167969 39.566,-104.985352 39.124201,-94.614258 35.454518,-97.426758 38.473482,-90.175781 45.021612,-93.251953 42.417881,-83.056641 41.371141,-81.782227 33.791132,-84.331055 30.252543,-90.439453 37.421248,-122.174835 37.47794,-122.181702 37.510628,-122.254486 37.56943,-122.346497 37.593373,-122.384949 37.620571,-122.489319 36.984249,-122.03064 36.553017,-121.893311 36.654442,-121.772461 36.482381,-121.876831 36.15042,-121.651611 36.274518,-121.838379 37.817717,-119.569702 39.31657,-120.140991 38.933041,-119.992676 39.13785,-119.778442 39.108019,-120.239868 38.586082,-121.503296 38.723354,-121.289062 37.878444,-119.437866 37.782994,-119.470825 37.973771,-119.685059 39.001377,-120.17395 40.709076,-73.948975 40.846346,-73.861084 40.780452,-73.959961 40.778829,-73.958931 40.78372,-73.966012 40.783688,-73.965325 40.783692,-73.965615 40.783675,-73.965741 40.783835,-73.965873 '''''' import StringIO import numpy as np import re import matplotlib.pyplot as plt def lp(l): return map(lambda m: float(m.group()),re.finditer(''[^, /n]+'',l)) data=np.array(map(lp,StringIO.StringIO(sdata))) xmn=np.min(data[:,0]) xmx=np.max(data[:,0]) ymn=np.min(data[:,1]) ymx=np.max(data[:,1]) # area of the point set bounding box area=(xmx-xmn)*(ymx-ymn) M_ITER=100 #maximum number of iterations THRESH=1e-10 # stopping threshold def em(x): print ''/nSTART EM'' mlst=[] mu0=np.mean( data , 0 ) # the sample mean of the data - use this as the mean of the low-precision gaussian # the mean of the high-precision Gaussian - this is what we are looking for mu=np.random.rand( 2 )*np.array([xmx-xmn,ymx-ymn])+np.array([xmn,ymn]) lam_lo=.001 # precision of the low-precision Gaussian lam_hi=.1 # precision of the high-precision Gaussian prz=np.random.rand( 1 ) # probability of choosing the high-precision Gaussian mixture component for i in xrange(M_ITER): mlst.append(mu[:]) l_hi=np.log(prz)+np.log(lam_hi)-.5*lam_hi*np.sum((x-mu)**2,1) #low-precision normal background distribution l_lo=np.log(1.0-prz)+np.log(lam_lo)-.5*lam_lo*np.sum((x-mu0)**2,1) #uncomment for the uniform background distribution #l_lo=np.log(1.0-prz)-np.log(area) #expectation step zs=1.0/(1.0+np.exp(l_lo-l_hi)) #compute bound on the likelihood lh=np.sum(zs*l_hi+(1.0-zs)*l_lo) print i,lh #maximization step mu=np.sum(zs[:,None]*x,0)/np.sum(zs) #mean lam_hi=np.sum(zs)/np.sum(zs*.5*np.sum((x-mu)**2,1)) #precision prz=1.0/(1.0+np.sum(1.0-zs)/np.sum(zs)) #mixure component probability try: if np.abs((lh-old_lh)/lh)<THRESH: break except: pass old_lh=lh mlst.append(mu[:]) return lh,lam_hi,mlst if __name__==''__main__'': #repeat the EM algorithm a number of times and get the run with the best log likelihood mx_prm=em(data) for i in xrange(4): prm=em(data) if prm[0]>mx_prm[0]: mx_prm=prm print prm[0] print mx_prm[0] lh,lam_hi,mlst=mx_prm mu=mlst[-1] print ''best loglikelihood:'', lh #print ''final precision value:'', lam_hi print ''point of interest:'', mu plt.plot(data[:,0],data[:,1],''.b'') for m in mlst: plt.plot(m[0],m[1],''xr'') plt.show()



¿Por qué no algo como esto?

  • Para cada punto, calcula la distancia desde todos los demás puntos y suma el total.
  • El punto con la suma más pequeña es tu centro.

Tal vez la suma no es la mejor métrica para usar. Posiblemente el punto con más "pequeñas distancias"?


Primero me gustaría expresar mi cariño por su método al ilustrar y explicar el problema ...

Si estuviera en su lugar, buscaría un algoritmo basado en la densidad como DBSCAN y luego, después de agrupar las áreas y eliminar los puntos de ruido , quedarán algunas (opciones) ... luego tomaré el grupo con la mayor densidad de apunta y calcula el punto promedio y encuentra el punto real más cercano . Hecho, encontré el lugar! :).

Saludos,


¿Qué hay de dividir el mapa en muchas zonas y luego encontrar el centro del plano en la zona con más plano? Algoritmo será algo como esto

set Zones[40] foreach Plane in Planes Zones[GetZone(Plane.position)].Add(Plane) set MaxZone = Zones[0] foreach Zone in Zones if MaxZone.Length() < Zone.Length() MaxZone = Zone set Center foreach Plane in MaxZone Center.X += Plane.X Center.Y += Plane.Y Center.X /= MaxZone.Length Center.Y /= MaxZone.Length



Suma sobre las distancias. Toma el punto con la menor distancia sumada.

function () { for i in points P: S[i] = 0 for j in points P: S[i] += distance(P[i], P[j]) return min(S); }