Matlab 优化for循环 矩阵,四个for循环 矩阵,怎么改正矩阵向量化?

只需一步,快速开始
扫一扫,访问微社区
查看: 8751|回复: 22|关注: 0
Matlab中for循环使用时出现超耗时语句怎样修改后高效?
<h1 style="color:# 麦片财富积分
新手, 积分 7, 距离下一级还需 43 积分
本帖最后由 haiou2008 于
19:32 编辑
我是matlab新手,使用win7 64位系统,Matlab2012a 64位。编写了一个经典SIR模型的例子,运行很慢,十分耗时。
我通过profile on,查看了一下代码的耗时,发现如下的一个语句十分的耗时,请大家帮我想一下办法!
这个语句是要查找矩阵中某一行中为1的列标号,矩阵我测试用的比较小,500左右,但实际使用时会是左右大小的稀疏邻接矩阵。
这次测试是重复1000次实验得到的,附件中有我完整的主函数,调用函数和数据集。希望能有人帮我,让我学习一下如何让matlab代码跑的飞快!提高研究效率。
下面的部分代码,解释如下:
I_ID为列向量,存储初始感染点的编号;&&neighbor_ID 为找到某个节点的所有邻居的编号;neighbor_State 为节点编号+节点状态;
完整的代码,见附件,希望得到大家的帮助,不胜感激!for i = 1:length(I_ID);
& && &&&I_i = I_ID(i);
& && &&&%%% 下面的语句,太耗时间
& && &&&neighbor_ID = Graph(I_i,:) == 1;& && &
& && &&&%%% 上面的语句,太耗时间
& && &&&neighbor_State = State_list(neighbor_ID,:);
& && &&&S_ID = neighbor_State((neighbor_State(:,2) == 0),1);& & %找到邻居中的S态节点
& && & for ii = 1:length(S_ID)
& && && && &S_i = S_ID(ii);
& && && && &if ( rand & beta )
& && && && && & State_list(S_i,2) = 5;& &%I态节点以bata概率感染邻居S态节点,暂时标记为5
& && && && &end
& && &&&end
& && &&&if ( rand &= gamma )
& && && &&&State_list(I_i,2) = 2;& && &&&%原始I态节点自己以gamma概率变为R态& && &&&
& && &&&end
& & end复制代码程序文件如下:
(18.78 KB, 下载次数: 2812)
23:00 上传
点击文件名下载附件
谢谢大家,希望得到回复。。
论坛优秀回答者
帖子最佳答案
关注者: 4260
你这个for循环可以向量化,你为什么要放在for循环里面?
为什么不一次性全部找出index
ind=find(Graph== 1);& &
math (博士、教授)Email: & &&&QQ:
我在网络上的言论、见解等只代表我个人的观念,与任何研究机构、商业公司等无关。欢迎你通过任何方式与我探讨学术和技术上的问题(学生提问的话,请在论坛上发帖提问)。最新日志:
<h1 style="color:# 麦片财富积分
math 发表于
你这个for循环可以向量化,你为什么要放在for循环里面?
为什么不一次性全部找出index
您好!非常感谢您的回复,我用在第一个for里面,是因为下面第二个for语句和if语句,要对index中的每一个数据进行分别判断是否&beta,如果第一个for向量化,可以实现这个功能吗?我还是新手,您能帮我看看如何修改吗?源代码,我已经放在附件中了,万分感谢!
<h1 style="color:# 麦片财富积分
大家可以帮我解答一下吗?我向量化用的不好,稍微复杂一点for循环和find操作就不行了,就只能一个一个找了。还做不到把向量化方法用到稍微复杂的情况下,希望大家帮我看看如何修改。
<h1 style="color:# 麦片财富积分
本帖最后由 haiou2008 于
14:47 编辑
论坛里还有没有大神帮忙解答一下啊?:'(:'(是大家都不会吗?还是觉得太简单。。请大家赐教啊!
<h1 style="color:# 麦片财富积分
有没有大神帮忙解答一下,受尽代码的摧残。。有没有效率高的方式?
MATLAB 基础讨论版块优秀回答者
<h1 style="color:#79 麦片财富积分
关注者: 171
要想加快程序的运行速度,已经算出的东西就绝对不再重算。
比如在你的程序中,同一个Graph(I_i,:)==1被重复计算了13721次,自然会很慢。
事实上,如math所说,你应该在所有的循环之外一次算出所有的neighbor_ID
neighbor_ID = (Graph(I_i,:) == 1);
然后在循环中用到neighbor_ID时,写成
neighbor_ID(I_i, :);
<h1 style="color:# 麦片财富积分
stellari 发表于
要想加快程序的运行速度,已经算出的东西就绝对不再重算。
比如在你的程序中,同一个Graph(I_i,==1被重复 ...
嗯,这个确实是大问题,我没能很好的理解math的意思,我尝试一下这样去写。如果还是很耗时间,还请您朵朵指导,非常感谢您!
论坛优秀回答者
关注者: 303
看了下你的程序,SIR_m2中graph的只用了两次,第一次是求M,第二次就是你说耗时的那次
而且你的graph非零元素全是1,所以完全可以把graph在生成的时候就变成一个logical类型,这样就不需要
Graph(I_i,:)==1,而可以直接用Graph(I_i,:),这样下边两行:
& && &&&neighbor_ID = Graph(I_i,:) == 1;& && &
& && &&&neighbor_State = State_list(neighbor_ID,:);
完全可以改成一行:
& && &&&neighbor_State = State_list(Graph(I_i,:),:);
另外注意到你这里Graph是对称的,而且整个SIR_m2中都没有改变过,所以建议你把
Graph(I_i,:)
Graph(:,I_i)
neighbor_State = State_list(Graph(:,I_i),:);
因为matlab内存管理上是按照列存储数据的(即使是稀疏阵也是),这样读取会更加高效些
在执行上边的改动之前,记得要修改Pretreatment,使得的输出Graph为logical类型,与此同时把Pretreatment稍作简化:
function Graph = Pretreatment(List)
ij = List(:,1:2) + 1;
n = max(ij(:));
Graph = sparse(ij(:,1), ij(:,2), 1, n, n);
Graph = (Graph + Graph') & 0;
除了上述这些,其他地方也可以有些改进,不过都影响不大,例如
1.阈值beta的判断那个小循环完全可以向量化处理
2. State_list(State_list(:,2) == 5,3) =& &%将节点感染时间记录,初始感染源的被感染时间默认0& &
& & State_list(State_list(:,2) == 5,2) = 1;& &%将新感染的节点变为I态
重复计算了两次State_list(:,2) == 5,完全可以只计算一次:
idx = State_list(:,2) == 5;
& & State_list(idx,3) = T_& &%将节点感染时间记录,初始感染源的被感染时间默认0
& & State_list(idx,2) = 1;& &%将新感染的节点变为I态
3.R_sum和I_sum你只要最大值,那么你完全可以在循环中完成,而没必要把每次的值都保存下来,到最后求最大值,这样还会导致matlab每次都有可能需要重新分配空间
4.State_list = [State_list, 1e99*ones(size(State_list,1), 1)];&&% 最后一列记录感染时间
State_list( State_list(:,2) == 1, 3) = 0;& && & %初始感染源的感染时间默认为0
5,6,7,。。。。
不过这些问题相比上述提到的那些都只算是小问题,影响有限
另外你这里如果graph并不是很大,能把graph生成为full矩阵(需要修改Pretreatment),可能也会提升一些效率,不过也要看具体情况
<h1 style="color:# 麦片财富积分
stellari 发表于
要想加快程序的运行速度,已经算出的东西就绝对不再重算。
比如在你的程序中,同一个Graph(I_i,==1被重复 ...
真的非常非常感谢您!根据你说的办法,我将neighbor_ID = (Graph(I_i,:) == 1);放进主函数中,算法效率得到极大的提升。在编程的过程中,我将好好记住您说的“要想加快程序的运行速度,已经算出的东西就绝对不再重算。”。再次感谢!
站长推荐 /3
筑起功能安全的堡垒 - 基于模型设计的软件开发
MATLAB中文论坛是全球最大的 MATLAB & Simulink 中文社区。用户免费注册会员后,即可下载代码,讨论问题,请教资深用户及结识书籍作者。立即注册加入我们吧!
MATLAB官方社交平台
MATLAB中文论坛微社区matlab 用for循环给矩阵赋值_百度知道
matlab 用for循环给矩阵赋值
利用 for 循环给3行4列矩阵赋值,当i&j时,bij=i+j。当i&j时,bij=i-j, i=j时 bij=1急!!!!在线等
我有更好的答案
for i=1:3for j=1:4if i&jb(i,j)=i+j;elseif i==jb(i,j)=1;elseb(i,j)=i-j;endendendend
采纳率:65%
为您推荐:
其他类似问题
for循环的相关知识
&#xe675;换一换
回答问题,赢新手礼包&#xe6b9;
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。  最近一周,对MATLAB有进行了新一轮的学习,对其矩阵化编程的思维有了更深入的了解。确实精妙!
  将矩阵A= [1 2 3; 2 4 3; 3 4 5]中所有的数字3替换为33.
如果还停留在C语言的思维可能就是
&& for i=1:3
if A(i,j)==3
A(i,j) = 33;
  而MATLAB语言则有更灵活的语法,
&& A(A==3) = 33
  这句的意思就是讲matlab中等于3的数复制为33;
  当在MATLAB中输入A==3
  得到的是一个逻辑数组,接下来的复制操作只对逻辑为真的部分进行。显然后一种写法代码更加简洁。
将A= [1 2;2 3; 3 4; 4 5]每行视为坐标;将5阶零矩阵的这四个位置复制为1;
  继续常规思维,也是最正常的思维就是每个位置赋值:
&& A= [1 2;2 3; 3 4; 4 5];
B = zeros(5);
B(A(i,1),A(i,2)) = 1;
  这里可以使用sub2ind这个函数,从字面意思已经知道,是将下标转换为索引值,具体原理可以help sub2ind以及type sub2ind(查看源码)
所以可以直接写成
&& A= [1 2;2 3; 3 4; 4 5];
&& B = zeros(5);
&& B(sub2ind(size(B), A(:,1), A(:,2)))=1
  深刻体会到矩阵处理问题的简洁之美!
统计矩阵A = [1 3 4; 5 3 2; 4 2 1]中3的个数
如果还停在初学C语言的思维,恐怕又是靠for解决问题
&& A = [1 3 4; 5 3 2; 4 2 1];
&& for i=1:3
if A(i,j)==3
  这使如果知道find函数和length函数,就会轻松不少:
&& length(find(A==3))
 总结,通过以上三个例子,可以看到:
  1、学习一门新的东西,一定要把握其精髓,不要固定步自封(比如一味使用for循环)、生搬硬套;
  2、就我现在体会,学习matlab最重要的是学习它丰富的函数和灵活的语法,也就是说这门语言处理运算的思维。
  3、作为一个技术人员,一定要偷懒,抠门。什么是偷懒,相同的功能,能用一行代码解决绝不用两行,什么是抠门,用最简洁的思维,最快的时间、最小的内存。
  4、敢想敢做,敢想:为什么不能用一行代码解决;敢做,敢于通过学习实现自己的想法。
阅读(...) 评论()求助,如何将如下for循环生成矩阵化为向量化运算,减少时间_百度知道
求助,如何将如下for循环生成矩阵化为向量化运算,减少时间
c=[0 0]for i=1:100for j=1:100d=[i,j]c=cat(1,c,d)endend
是用Matlab做的
我有更好的答案
其实你现在的时间主要是花费在了屏幕打印上,每循环一次就要打印一次,很浪费时间,其实FOR循环本身不耗时间的,如果你只需要最后结果的话,不妨让程序不要输出中间过程。(语句加分号)ticc=[0 0];for i=1:100
for j=1:100
c=cat(1,c,d);
endendctoc******************我的电脑是一秒就好了。如果输出中间过程,我的电脑上是跑个没完的
采纳率:65%
试下reshape(1,数据总数),希望对你有帮助。
为您推荐:
其他类似问题
生成矩阵的相关知识
&#xe675;换一换
回答问题,赢新手礼包&#xe6b9;
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。matlab中矩阵的行(列)向量化运算本质上是for循环吗? - 知乎5被浏览522分享邀请回答0添加评论分享收藏感谢收起

我要回帖

更多关于 python for循环优化 的文章

 

随机推荐