1

私は 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 で記述されています。

4

2 に答える 2

1

Pとの操作Qは本質的に逐次的であるため (反復更新)、これ以上のことはできないと思います。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
于 2012-12-05T17:27:41.307 に答える
1

これは、すべてのコードをベクトル化できないケースの 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
于 2012-06-04T15:06:11.947 に答える