簡體   English   中英

用於在Matlab中計算大量位置的成對距離的高效算法

[英]Efficient algorithm to calculate pairwise distances for a large set of locations in matlab

我最近在Matlab中使用大量位置計算球面距離時遇到問題。 這是問題所在:

1.locations是經度和緯度,存儲在尺寸為nx2的矢量位置中,其中n = 10 ^ 5。

2.我想計算矢量位置中任意兩個位置之間的球面距離。 請注意,生成的距離矩陣可能稀疏,也可能不稀疏,因為如果沒有距離,我將無法對其進行檢查。 我們假設它是稀疏的,因為我們可以用一個數字(例如1000)來截斷距離。(單位是km),並且得出的距離矩陣足以滿足我的使用要求。

3.我嘗試了兩種方法進行計算,但每種方法都有缺點。

PS:我在帶有MATLAB 2014學生版的Mac OS上運行代碼。 函數great_circle_distance()非常類似於Matlab內置函數,該函數通過地理空間坐標計算任意兩個位置之間的大圓距離。 這里的問題與該功能的使用無關。

預先感謝各種建議。

--Disc

方法一:

dist = zeros(n, 1);
dist_vec = [];
dist_id = [];
dist_id2 = [];
for i =1:n
dist = great_circle_distance(locs(i, :), locs);
dist_temp=(dist<300) &(dist>0);   % for example, consider the distance between 0 and 300
[dist_id_temp, dist_id2_temp,dist_vtemp]=find(dist_temp);
dist_vec_temp=dist(dist_id_temp);
dist_id=[dist_id; dist_id_temp];
dist_id2=[dist_id2; dist_id2_temp];
dist_vec=[dist_vec; dist_vec_temp];

if mod(i, 1000) == 0

    i

end
end
dist_mat = sparse(dist_id, dist_id2, dist_vec);

這樣做的缺點是花了很長時間(至少48小時)才能完成,但是在2-5G左右它並沒有消耗太多的內存。

方法2:

d = pdist(locs, @great_circle_distance);
[i, j] = find(tril(true(n), -1)); % extract index below main diagonal
d = d';
a = [i, j, d];
con = d == 0;   % specify condition. 
a(con, :) = [];   % delete rows satisfying condition con.
clear i j d;
i = a(:, 1);
j = a(:, 2);
d = a(:, 3);
dist_mat = sparse(i, j, d);

這種方法的缺點是在代碼中計算d時會消耗過多的內存(超過15G)。

1)方法1

您在構建中間變量(改變大小等的數組)的方式上效率很低。 考慮以下改進的實現:

% given some data (longitude/latitude)
locs = rand(N,2);    % N = 10^5 in your case

% pick an appropriate size (guesstimate the number of nonzeros in the sparse mat)
nzmx = ...;

% compute pairwise-distance matrix (only those satisfying some condition)
D = spalloc(N, N, nzmx);
for i=1:N
    d = great_circle_distance(locs(i,:), locs);
    idx = find(100<d & d<400);   % distances in the range [100,400] km
    D(idx,i) = d(idx);
end

請注意,對於N=10^5個條目, double精度類型的完整距離矩陣將消耗: N*N*8個字節,或大約((10^5)^2*8)/2^30 = 74.5 GB的內存(那是千兆字節! 因此,很明顯,我假設即使應用條件后,您也有足夠的RAM來容納稀疏矩陣,否則無法完全進行計算(在這種情況下,您必須將其分解為多個塊,然后一次計算一個)時間)。 假設只有5%的矩陣是非零的,那就像是4GB的連續內存。 因此,您必須在上面的代碼中為nzmx選擇適當的值。

您提到距離函數great_circle_distance與此處的討論無關。 只要確保已將其正確矢量化,否則可能會嚴重影響性能。

更新 :這是僅填充稀疏矩陣的下半部分的一種可能的改進:

D = spalloc(N, N, nzmx);
for i=1:N-1
    d = great_circle_distance(locs(i,:), locs(i+1:end,:));
    idx = find(100<d & d<400);
    if isempty(idx), continue; end
    D(idx+i,i) = d(idx);
end

2)方法2

顯然,由於您使用的是pdist ,它將計算整個矩陣(只有一半)。 因此,您必須確保有足夠的內存來存儲它(根據我的計算,大約((N*(N-1)/2)*8)/2^30 = 37.25 GB )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM