【问题标题】:normrnd() and norm() operations without "for loop"normrnd() 和 norm() 操作没有“for循环”
【发布时间】:2015-02-03 16:12:39
【问题描述】:

我一直在寻找编写以下没有“for 循环”的代码。我研究了数组操作,例如bsxfun()arrayfun,或其他 MATLAB 内置函数,但无法真正弄清楚。

n = 10;
d= 2;

x = rand(n,d);
P_best = rand(n,d);
V_i = rand(n,d)
g = rand(1,d);
r_t = rand(n,1);


a1 = 0.91;
a2 = 0.21;
a3 = 0.51;
a4 = 0.58;

l = a1*a3/(n^a2*d^a4);

for i=1:n
    N_p(i,:) = 1.4962*r_t(i)*(normrnd(P_best(i,:),l*norm(x(i,:)-P_best(i,:),2))-x(i,:));
    N_g(i,:) = 1.4962*r_t(i)*(normrnd(g,l*norm(x(i,:)-g,2))-x(i,:));
end

V_o = 0.7298*V_i+N_p+N_g

任何解决方案将不胜感激。 另外,我的第二个问题是,替换上述循环是否会减少运行时间,尤其是对于大型数据集?还有其他可以减少运行时间的技巧吗?我问这样的问题的原因是我正在处理大型数据集,显然减少我工作每个步骤的运行时间将导致流程成本的大幅降低。

【问题讨论】:

  • 请解释代码的用途,最好是包含输入和所需输出的示例
  • 这是我在主要工作中需要的样本。您在顶部看到的随机矩阵只是为我的算法准备一些样本数据。此代码的目的是将粒子群优化中的粒子速度从V_i 更新为V_o。我在我的问题中主要寻找的是做什么而不是“for循环”。

标签: matlab for-loop vectorization normal-distribution norm


【解决方案1】:

讨论与代码

您可以使用基于bsxfun 的矢量化版本删除该loop -

N_g_sigma = l*sqrt(sum(bsxfun(@minus,x,g).^2,2));
N_g_normrnd = bsxfun(@plus,randn(size(N_g_sigma)).*N_g_sigma,g);
N_g = bsxfun(@times,N_g_normrnd - x,1.4962*r_t);

N_p_sigma = l*sqrt(sum(bsxfun(@minus,x,P_best).^2,2));
N_p_normrnd = bsxfun(@plus,randn(size(N_p_sigma)).*N_p_sigma,P_best);
N_p = bsxfun(@times,N_p_normrnd - x,1.4962*r_t);

它基于normrnd.m黑客版本,在Stackoverflow - Improve speed of NORMRND for a family of distributions in MATLAB 的另一个问题中也被利用,它为我们带来了巨大的加速。

这里要注意的是normrnd.m使用给定标量musigma的随机数生成,如其语法所示-

function r = normrnd(mu,sigma,varargin); 
%NORMRND Random arrays from the normal distribution...

通过所提议的矢量化技术,我们在每次迭代中提供一个musigma 的数组,而不是标量值,从而使vectorization 生效。 p>


快速运行结果

*****************  Datasize : n = 100000 , d = 10 *******************
-------------------------------------- With original loopy code
Elapsed time is 82.344671 seconds.
-------------------------------------- With Proposed vectorized code
Elapsed time is 0.033276 seconds.

*****************  Datasize : n = 10000 , d = 100 *******************
-------------------------------------- With original loopy code
Elapsed time is 7.776902 seconds.
-------------------------------------- With Proposed vectorized code
Elapsed time is 0.032324 seconds.

这里看到的巨大加速与使用矢量化的other normrnd related problem 获得的加速一致。

【讨论】:

  • 感谢您的回答。它看起来像我正在寻找的东西。我会试一试并在这里发布结果。
  • @Omid 添加了一些我自己的运行时结果!
  • 我得到了非常有趣的结果。我希望有一种方法可以将图像附加到此评论中,这样我就可以以图表的形式展示我的运行时nd 的不同值。无论如何,运行时间确实增加了。当n 相当大时,比方说高于 500,这种差异更加显着。有趣的是,我没有看到 forparfor 之间的运行时差异很大。我期待看到parfor 表现更好,但看到了相反的结果。有什么理由吗?或者我没有正确使用parfor
  • @Omid 试试一些免费的图片上传网站,比如http://postimage.org/ 并链接到这里?在parfor 的事情上,真的不是专家,bsxfun 为我做了所有的工作:)
【解决方案2】:

对不起,我再次检查了您的问题,我无法帮助删除 for 循环。关于提高 for 循环速度的一些建议:

% fastest way: Elapsed time is 0.000006 seconds.
tic
for i=n:1
  N_p(i,:) = 1.4962*r_t(i)*(normrnd(P_best(i,:),l*norm(x(i,:)-P_best(i,:),2))-x(i,:));
  N_g(i,:) = 1.4962*r_t(i)*(normrnd(g,l*norm(x(i,:)-g,2))-x(i,:));
end
toc

% slowest way: Elapsed time is 0.004444 seconds.
tic
for i=1:n
  N_p(i,:) = 1.4962*r_t(i)*(normrnd(P_best(i,:),l*norm(x(i,:)-P_best(i,:),2))-x(i,:));
  N_g(i,:) = 1.4962*r_t(i)*(normrnd(g,l*norm(x(i,:)-g,2))-x(i,:));
end
toc

% 2nd choice: Elapsed time is 0.000969 seconds.
tic
N_p2(n, 2) = nan;
N_g2(n, 2) = nan;
for i=1:n
  N_p2(i,:) = 1.4962*r_t(i)*(normrnd(P_best(i,:),l*norm(x(i,:)-P_best(i,:),2))-x(i,:));
  N_g2(i,:) = 1.4962*r_t(i)*(normrnd(g,l*norm(x(i,:)-g,2))-x(i,:));
end
toc

【讨论】:

  • 感谢您的回答。我有一个问题,那些我会怎么样?因为不再有循环,我想变量“i”不会被定义。
  • 感谢比较。真的很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-10
  • 2012-10-20
  • 1970-01-01
相关资源
最近更新 更多