MATLAB:快速计算Adamic-Adar分数

时间:2016-07-31 17:10:11

标签: algorithm performance matlab network-programming vectorization

我有一个网络的邻接矩阵,想要计算Adamic-Adar得分。它按以下方式定义:对于每对边x和y,让z为它们的一个共同邻居,并且| z |是邻居的程度。

现在,分数被定义为所有常见邻居z的总和:

enter image description here

例如参见this paper, page 3

我为MATLAB编写了一个小算法,但它使用了两个for循环。我确信它可以更快,但我不知道如何。你能说明一下如何加快这个速度吗?

% the entries of nn will always be 0 or 1, and the diagonal will always be 0
nn=[0 0 0 0 1 0; ...
    0 0 0 1 1 0; ...
    0 0 0 0 1 0; ...
    0 1 0 0 0 1; ...
    1 1 1 0 0 0; ...
    0 0 0 1 0 0]; 

deg=sum(nn>0);
AAScore=zeros(size(nn));

for ii=1:length(nn)-1
    for jj=ii+1:length(nn)
        NBs=nn(ii,:).*nn(jj,:);
        B=NBs.*deg;
        C=B(B>1);
        AAScore(ii,jj)=sum(1./log(C));
    end
end
AAScore

我很感激任何建议,谢谢!

比较运行时

我的nn有~2%的条目,所以它可以近似为:

kk=1500;
nn=(rand(kk)>0.98).*(1-eye(kk));
  • 我的双倍:37.404445秒。
  • Divakar的第一个解决方案:58.455826秒。
  • Divakar的更新解决方案:22.333510秒。

1 个答案:

答案 0 :(得分:1)

首先,获取将要设置的输出数组中的索引,即非零。查看代码,我们可以注意到,我们基本上从输入矩阵AND-ing开始对每一行执行nn1s。鉴于我们正在处理0striu(...,1),这基本上转化为执行矩阵乘法。因此,矩阵乘法结果中的非零将指示需要计算的sqaured矩阵输出数组中的位置。这应该是有效的,因为我们将迭代较小的元素。最重要的是,由于我们得到一个上三角矩阵输出,这应该通过使用[R,C] = find(triu(nn*nn.'>0,1)); vals = sum(1./log(bsxfun(@times,nn(R,:).*nn(C,:),deg)),2); out=zeros(size(nn)); out(sub2ind(size(out),R,C)) = vals; 的掩码进一步减少计算。

遵循这些想法,这是一个实现 -

nn

对于输入矩阵bsxfun(@times,nn(R,:).*nn(C,:),deg) less-sparsey 且非常庞大的情况,您会感到计算R,C的瓶颈。因此,对于这种情况,您可以直接使用这些[R,C] = find(triu(nn*nn.',1)); out=zeros(size(nn)); for ii =1:numel(R) out(R(ii),C(ii)) = sum(1./log(nn(R(ii),:).*nn(C(ii),:).*deg)); end 索引来执行计算,以更新输出数组中的相应选择位置。

因此,另一种实现方式是 -

R,C

可以在上述两种方法之间建立中间关系,方法是从nn(R,:)索引开始,然后选择nn(C,:)之外的行和来自PHP >= 7.0 required yours is 5.6.15的各行。并且以较低的复杂度迭代地使用这些块的向量化实现。设置块大小可能很棘手,因为它在很大程度上取决于系统资源,涉及的输入数组大小以及它的稀疏性

相关问题