【问题标题】:How would you vectorize this nested loop in matlab/octave?您将如何在 matlab/octave 中对这个嵌套循环进行矢量化?
【发布时间】:2012-06-04 12:38:49
【问题描述】:

我在 MATLAB/Octave 中对这个棘手的循环进行矢量化处理:

[nr, nc] = size(R);
P = rand(nr, K);
Q = rand(K, nc);

for i = 1:nr
   for j = 1:nc
      if R(i,j) > 0
          eij = R(i,j) - P(i,:)*Q(:,j);
          for k = 1:K
          P(i,k) = P(i,k) + alpha * (2 * eij * Q(k,j) - beta * P(i,k));
          Q(k,j) = Q(k,j) + alpha * (2 * eij * P(i,k) - beta * Q(k,j));
          end
      end
   end
end

代码尝试将 R 分解为 P 和 Q,并使用更新规则逼近最近的 P 和 Q。例如,设 R = [3 4 0 1 1; 0 1 0 4 4; 5 4 3 1 0; 0 0 5 4 3; 5 3 0 2 1],K=2,α=0.01,β=0.015。在我的真实案例中,我将使用一个巨大的稀疏矩阵 R(这就是我需要向量化的原因),而 K 仍然很小(小于 10)。整个脚本的目标是根据非零元素为 R 中的每 0 个元素生成一个预测值。我从here 得到这段代码,最初是用 Python 编写的。

【问题讨论】:

  • 你能描述一下这段代码在做什么,而不是要求我们解码你的代码吗?
  • (顺便提一下,endforendif 在 Matlab 中不受支持。)
  • 在 Matlab 中用简单的 end 替换 endfor 和 endif
  • 这段代码尝试将 R 分解为 P 和 Q,并使用更新规则逼近最近的 P 和 Q
  • 也许给出矩阵 R、P、Q 的输入/输出示例?

标签: matlab octave vectorization


【解决方案1】:

这看起来像是并非所有代码都可以向量化的情况之一。不过,你可以让它比现在好一点。

[nr, nc] = size(R);
P = rand(nr, K);
Q = rand(K, nc);

for i = 1:nr
   for j = 1:nc
      if R(i,j) > 0
          eij = R(i,j) - P(i,:)*Q(:,j);
          P(i,:) = P(i,:) + alpha * (2 * eij * Q(:,j)' - beta * P(i,:));
          Q(:,j) = Q(:,j) + alpha * (2 * eij * P(i,:)' - beta * Q(:,j));
      end
   end
end

【讨论】:

  • 对最里面的循环进行向量化会好一些,但问题是另外两个循环贡献的循环数最多,R的大小很大。
【解决方案2】:

由于PQ 上的操作本质上是串行的(迭代更新),我认为你不能做得更好。您可以在循环中保存if

[nr, nc] - size(R);
P = rand(nr, K);
Q = rand(K, nc);

[nzi nzj] = find( R > 0 );
for ii=1:numel(nzi)
    i = nzi(ii);
    j = nzj(ii);
    eij = R(i,j) - P(i,:)*Q(:,j);
    P(i,:) = P(i,:) + alpha * (2 * eij * Q(:,j)' - beta * P(i,:));
    Q(:,j) = Q(:,j) + alpha * (2 * eij * P(i,:)' - beta * Q(:,j));
end

【讨论】:

    猜你喜欢
    • 2018-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-25
    相关资源
    最近更新 更多