【问题标题】:Vectorization of 2 for loops in MATLABMATLAB中2个for循环的向量化
【发布时间】:2023-03-25 03:14:01
【问题描述】:

我刚刚开始探索矢量化的世界。我得到了一维矢量化,但我在矢量化以下代码时遇到了问题。如果可能的话,我想至少取消一个 for 循环 b/c 我计划在更大的数据集上使用它进行多次迭代,因此节省计算时间至关重要。

CityPairs = [7 3
3 1
3 1
1 7
7 1
3 4
5 1
4 6];
Offices = [1;3;7];
nOffices = size(Offices,1);

connection = zeros(nOffices);
for i = 1:nOffices
    for j = 1:nOffices
        connection(i,j) = sum(Offices(i) == CityPairs(:,1)...
            & CityPairs(:,2) == Offices(j));
    end
end   
disp(connection)

在本例中,有 7 个城市,其中 3 个设有办事处。我想要一个有办公室的城市的成对矩阵来捕获每个城市之间所有单向连接的总和。上述问题的答案应该是:

 0     0     1
 2     0     0
 1     1     0

欢迎提出任何建议。提前致谢。

基思

【问题讨论】:

  • connection(i,:) = connection(i,:); 有什么原因吗?否则删除该行。
  • 它是我所做的其他事情的一部分,在这里不重要 - 我已将其删除。
  • 那么你想要另一个答案还是你的问题解决了?
  • 问题已解决。我只是在 6 小时后才能发布自己的答案。感谢您提供替代解决方案 - 我稍后会检查它们并为那些正常工作的解决方案表示赞赏。

标签: matlab vectorization


【解决方案1】:

这是sparse 的替代解决方案:

dims = max(max(CityPairs), max(Offices));
A = sparse(CityPairs(:, 1), CityPairs(:, 2), 1, dims(1), dims(2));
result = full(A(Offices, Offices));

与建议的 bsxfun 解决方案相比,这应该会加快您的计算速度1


1 在 MATLAB 2012a 上运行速度提高 5 倍(Windows Server 2008 R2 在 2.27GHz 16 核 Intel Xeon 处理器上运行)

【讨论】:

  • 不错,我总是忘记稀疏堆积。
  • Eitan,我喜欢这个。工作很快,但我遇到了一个问题。我的数据集动态变化,我遇到了这样一种情况,即城市对中的一列不再具有大于最大办公室索引的城市索引,这会破坏完整操作。有什么想法吗?
  • 以上我的意思是说值而不是索引。
  • @user2913719 你能举个例子吗?我看不出它是如何破坏操作的。
  • 好的,在小例子中我提供了它没有(应该首先检查),但在 20K+ 的更大样本集上它是,但我也正在发生其他事情。让我们进行更多调查,同时我会为您提供反馈!
【解决方案2】:

你的任务是一些选择性的交叉制表。您可以通过累积感兴趣位置的计数轻松完成此操作,由您的Offices 索引:

% Row and col subs
[~,rsubs] = ismember(CityPairs(:,1),Offices);
[~,csubs] = ismember(CityPairs(:,2),Offices);

% Select where both belong to Offices, i.e. non 0
subs = [rsubs,csubs];
subs = subs(all(subs,2),:);

% Accumulate
accumarray(subs,1)

结果

ans =
     0     0     1
     2     0     0
     1     1     0

如果你有统计工具箱,你可以直接使用crosstab,但是你需要选择感兴趣的行和列:

crosstab(CityPairs(:,1),CityPairs(:,2))
ans =
     0     0     0     0     1
     2     0     1     0     0
     0     0     0     1     0
     1     0     0     0     0
     1     1     0     0     0

【讨论】:

  • 其实你可以直接用CityPairsaccumarray,然后选择匹配Offices的行和列,即:A = accumarray(CityPairs, 1); result = A(Offices, Offices);...(这有点像我的解决方案sparse)。
【解决方案3】:

Cedric Wannaz 在 MathWorks 论坛上提供的答案

“矢量化”此设置并非易事,因为有些操作需要一些查找表,并且存在累积(除非您找到技巧)。这可能会使没有 FOR 循环的方法比基于循环的基本方法更复杂(代码方面)。所以让我们先从技巧开始;-) ..

 A = double( bsxfun(@eq, CityPairs(:,1), Offices.') ) ;
 B = double( bsxfun(@eq, CityPairs(:,2), Offices.') ) ;
 A.' * B

替代方法:http://www.mathworks.com/matlabcentral/answers/91294-vectorization-of-2-for-loops-in-matlab

【讨论】:

    猜你喜欢
    • 2014-05-16
    • 1970-01-01
    • 2013-12-22
    • 2012-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    • 1970-01-01
    相关资源
    最近更新 更多