Ich möchte ein Raster aus Stichproben erstellen. Ich könnte einen maschinellen Lern-Clustering-Algorithmus, wie k-means, verwenden, aber ich möchte die Zentren auf ungefähr gleichförmige Verteilung beschränken.Erstellen Sie ein ungefähr gleichmäßiges Gitter aus Zufallsstichprobe (Python)
Ich habe einen Ansatz mit der scikit-learn Suche nächste Nachbarn gefunden: Wählen Sie einen Punkt nach dem Zufallsprinzip, löschen Sie alle Punkte innerhalb Radius r dann wiederholen. Das funktioniert gut, aber ich frage mich, ob jemand einen besseren (schnelleren) Weg hat, dies zu tun.
Als Reaktion auf die Kommentare, die ich zwei alternative Methoden versucht haben, wendet man sich als viel langsamer die andere ist etwa die gleiche ...
Methode 0 (mein erster Versuch):
def get_centers0(X, r):
N = X.shape[0]
D = X.shape[1]
grid = np.zeros([0,D])
nearest = near.NearestNeighbors(radius = r, algorithm = 'auto')
while N > 0:
nearest.fit(X)
x = X[int(random()*N), :]
_, del_x = nearest.radius_neighbors(x)
X = np.delete(X, del_x[0], axis = 0)
grid = np.vstack([grid, x])
N = X.shape[0]
return grid
Methode 1 (unter Verwendung der vorberechneten graph):
def get_centers1(X, r):
N = X.shape[0]
D = X.shape[1]
grid = np.zeros([0,D])
nearest = near.NearestNeighbors(radius = r, algorithm = 'auto')
nearest.fit(X)
graph = nearest.radius_neighbors_graph(X)
#This method is very slow even before doing any 'pruning'
Methode 2:
def get_centers2(X, r, k):
N = X.shape[0]
D = X.shape[1]
k = k
grid = np.zeros([0,D])
nearest = near.NearestNeighbors(radius = r, algorithm = 'auto')
while N > 0:
nearest.fit(X)
x = X[np.random.randint(0,N,k), :]
#min_dist = near.NearestNeighbors().fit(x).kneighbors(x, n_neighbors = 1, return_distance = True)
min_dist = dist(x, k, 2, np.ones(k)) # where dist is a cython compiled function
x = x[min_dist < 0.1,:]
_, del_x = nearest.radius_neighbors(x)
X = np.delete(X, del_x[0], axis = 0)
grid = np.vstack([grid, x])
N = X.shape[0]
return grid
diese Rennen wie folgt:
N = 50000
r = 0.1
x1 = np.random.rand(N)
x2 = np.random.rand(N)
X = np.vstack([x1, x2]).T
tic = time.time()
grid0 = get_centers0(X, r)
toc = time.time()
print 'Method 0: ' + str(toc - tic)
tic = time.time()
get_centers1(X, r)
toc = time.time()
print 'Method 1: ' + str(toc - tic)
tic = time.time()
grid2 = get_centers2(X, r)
toc = time.time()
print 'Method 1: ' + str(toc - tic)
Methode 0 und 2 etwa gleich sind ...
Method 0: 0.840130090714
Method 1: 2.23365592957
Method 2: 0.774812936783
Guter Punkt. Ich hatte eine alternative Version, bei der ich nur das "nächste" Objekt am Anfang anpasste, und dann die Punkte, die ich bisher gelöscht hatte, im Auge behielt. Es war aber eigentlich langsamer, ich denke, das Problem war, dass man beim Nachrüsten eine Beschleunigung bekommt, wenn das verbleibende Sample schrumpft. Deine Idee könnte das umgehen. Ich werde es versuchen. –
Hatte einen Versuch bei diesem Ansatz (siehe Änderungen) scheint nicht viel zu helfen ... –