在matlab中有效地计算双和?

x.y*_*... 4 performance matlab

我正在寻找一种编程这个总和比率的最佳方法.作为输入,我有两个向量v_mn,每个x_mn都有(M*N)x1元素.

比例的形式如下:

式

所述载体x_mn0-1载体,所以当x_mn=1,配给被r上方和当给定x_mn=0的比率0.

向量v_mn是包含实数的向量.

我做了这样的分母,​​但它需要很多次.

function r_ij = denominator(v_mn, M, N, i, j)
%here x_ij=1, to get r_ij.
S = [];
for m = 1:M
  for n = 1:N
    if (m ~= i)
      if (n ~= j)
        S = [S v_mn(i, n)];
      else
        S = [S 0];
      end
    else
      S = [S 0];
    end
  end
end
r_ij = 1+S;
end
Run Code Online (Sandbox Code Playgroud)

你能在matlab中做一个好方法吗?你可以忽略这个比例,给我一个更复杂的分母.

编辑:对不起,我写的不是很好.在ij之间存在一些数字1..M1..N分别.如您所见,该比率r是许多值(M*N值).所以我只计算了价值ij.更准确地说,我认为x_ij=1.此外,我将矢量v_mn转换为矩阵,这就是我使用双索引的原因.

Rod*_*uis 5

如果重塑数据,则总和只是重复的矩阵/向量乘法.

下面是一个实现mn,用一个简单的速度/相等测试一起:

clc

%# some arbitrary test parameters
M = 250;
N = 1000;
v = rand(M,N);   %# (you call it v_mn)
x = rand(M,N);   %# (you call it x_mn)

m0 = randi(M,1); %# m of interest
n0 = randi(N,1); %# n of interest 


%# "Naive" version
tic
S1 = 0;
for mm = 1:M %# (you call this m')
    if mm == m0, continue; end
    for nn = 1:N %# (you call this n')
        if nn == n0, continue; end
        S1 = S1 + v(m0,nn) * x(mm,nn);
    end
end
r1 = v(m0,n0)*x(m0,n0) / (1+S1);
toc


%# MATLAB version: use matrix multiplication!
tic

ninds = [1:m0-1 m0+1:M];
minds = [1:n0-1 n0+1:N];
S2 = sum( x(minds, ninds) * v(m0, ninds).' );
r2 = v(m0,n0)*x(m0,n0) / (1+S2);

toc


%# Test if values are equal
abs(r1-r2) < 1e-12
Run Code Online (Sandbox Code Playgroud)

我机器上的输出:

Elapsed time is 0.327004 seconds.   %# loop-version
Elapsed time is 0.002455 seconds.   %# version with matrix multiplication
ans =  
     1                              %# and yes, both are equal
Run Code Online (Sandbox Code Playgroud)

所以加速是~133×

现在这是单个m和的值n.要对和的所有值执行此操作,您可以使用(优化的)双循环:mn

r = zeros(M,N);
for m0 = 1:M   
    xx = x([1:m0-1 m0+1:M], :);
    vv = v(m0,:).';
    for n0 = 1:N
        ninds    = [1:n0-1 n0+1:N];        
        denom    = 1 + sum( xx(:,ninds) * vv(ninds) );
        r(m0,n0) = v(m0,n0)*x(m0,n0)/denom;        
    end
end
Run Code Online (Sandbox Code Playgroud)

在我的电脑上完成约15秒M = 250, N= 1000(R2010a).

编辑:实际上,经过多一点思考,我能够将其全部减少到这个:

denom = zeros(M,N);
for mm = 1:M    
    xx = x([1:mm-1 mm+1:M],:);
    denom(mm,:) = sum( xx*v(mm,:).' ) - sum( bsxfun(@times, xx, v(mm,:)) );    
end
denom = denom + 1;

r_mn = x.*v./denom;
Run Code Online (Sandbox Code Playgroud)

在不到1秒的时间内完成N = 250并且M = 1000:)