我已經創建了一個使用大小爲4000x300的k-means(4000個質心,每個具有300個特徵)的碼本。然後使用碼本標記一個輸入矢量(以便稍後進行分箱)。輸入向量的大小爲Nx300,其中N是我接收到的輸入實例的總數。是否有可能優化這個Matlab代碼來做矢量量化與質心從k-均值?
要計算標籤,我計算每個輸入向量的最接近的質心。爲此,我將每個輸入向量與所有質心進行比較,並選擇距離最小的質心。標籤就是該質心的索引。
我當前的Matlab代碼的樣子:
function labels = assign_labels(centroids, X)
labels = zeros(size(X, 1), 1);
% for each X, calculate the distance from each centroid
for i = 1:size(X, 1)
% distance of X_i from all j centroids is: sum((X_i - centroid_j)^2)
% note: we leave off the sqrt as an optimization
distances = sum(bsxfun(@minus, centroids, X(i, :)) .^ 2, 2);
[value, label] = min(distances);
labels(i) = label;
end
然而,這段代碼仍然是相當緩慢的(對於我而言),我希望有可能會進一步優化代碼的方式。
一個明顯的問題是,有一個for循環,這是Matlab的良好性能的禍根。我一直試圖想出一種方法來擺脫它,但沒有運氣(我研究了與bsxfun一起使用arrayfun,但沒有得到它的工作)。或者,如果有人知道任何其他方式加快速度,我將不勝感激。
更新
做一些搜索後,我找不到用Matlab一個很好的解決方案,所以我決定來看看什麼是Python的scikits.learn包用於「euclidean_distance」(縮短):
XX = sum(X * X, axis=1)[:, newaxis]
YY = Y.copy()
YY **= 2
YY = sum(YY, axis=1)[newaxis, :]
distances = XX + YY
distances -= 2 * dot(X, Y.T)
distances = maximum(distances, 0)
其使用歐幾里德距離的二項式形式((XY)^ 2 - >的x^2 + Y^2 - 2XY),其從我讀過通常運行速度更快。我完全未經測試的Matlab的翻譯是:
XX = sum(data .* data, 2);
YY = sum(center .^ 2, 2);
[val, ~] = max(XX + YY - 2*data*center');
相關:[pdist2相當於MATLAB版本7](http://stackoverflow.com/a/7774323/97160) – Amro 2012-07-10 20:26:42