【问题标题】:Is it possible to vectorize code which operates on submatrices along the same dimension in two matrices?是否可以向量化在两个矩阵中沿相同维度对子矩阵进行操作的代码?
【发布时间】:2013-11-12 15:02:21
【问题描述】:

我为冗长的标题道歉。 请考虑以下代码,它可能会出现在k-means 集群中。

rng(1)
num_samples = 10;
samples = randi(100, num_samples, 3);
cluster_centroids = randi(16,3);
cluster_indices = zeros(num_samples,1);

for index = 1:num_samples
    distances = sqrt(sum((samples(index) - cluster_centroids).^2, 2));
    cluster = find(distances == min(distances), 1)
    cluster_indices(index) = cluster;
end

有没有办法将它向量化并移除 for 循环,以便我们有效地处理所有样本(它们是三个整数的元组)?

【问题讨论】:

  • 在矢量化之前,该代码甚至似乎都没有返回合理的输出。 cluster_indices = zeros(num_samples); 应该是 cluster_indices = zeros(num_samples,1); 吗?
  • 是的,应该。我已经更新了问题。

标签: matlab matrix


【解决方案1】:

我在底部列出的现有代码存在几个问题,但首先是矢量化答案。答案的核心类似于my past solution。我对您的变量稍作修改,并添加了更多解释:

[nPoints,nDims] = size(samples);
k = 3; % ? size(cluster_centroids,1)

% Calculate all high-dimensional distances at once
% (NxDx1 - 1xDxK => NxDxK)
kdiffs = bsxfun(@minus,samples,permute(cluster_centroids,[3 2 1]));
distances = sum(kdiffs.^2,2); % no need to do sqrt
distances = squeeze(distances); % Nx1xK => NxK

distances 是矢量化的重要值。剩下的就很简单了:

% Find closest cluster center for each point
[~,cluster_indices] = min(distances,[],2); % Nx1

那么您将需要为以下迭代更新集群中心:

cluster_centroids_new = zeros(k,nDims);
for i=1:k,
    indk = cluster_indices==i;
    clustersizes(i) = nnz(indk);
    cluster_centroids_new(i,:) = mean(samples(indk,:))';
end

要对此代码进行一些讨论,请注意cluster_centroids_new 对每个集群都有一行,但如果集群没有成员,则该行将是NaNs。

有问题的代码问题:

  1. cluster_indices 被初始化为矩阵而不是向量。修复:cluster_indices = zeros(num_samples,1);(如 horchler 所述)。
  2. 您没有在distances 计算中正确索引samples。将 samples(index) 更改为 samples(index,:) 以提取样本。
  3. 每个 N 维样本与 cluster_centroids 之间的距离需要为 sum((repmat(samples(index,:),size(cluster_centroids,1),1) - cluster_centroids).^2, 2) 以计算样本与所有 k=size(cluster_centroids,1) 集群的距离。
  4. 不一定是错误,但请确保您的意思是 cluster_centroids = randi(16,3);,它给出了一个 3x3 矩阵,其中数字从 1 到 16。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-17
    • 1970-01-01
    • 1970-01-01
    • 2012-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多