Matlab心得及学习方法(不断更新)
P.S. 那些网上转载个人文章不写明出处的傻眼了吧?!老子更新了!
发现如今不少人(找工做的或者读博的)都想要学习或者正在学习Matlab,问我要怎么学习。其实我虽然写Matlab代码的经验还算丰富,可是还不能说是一个很好的Matlab编程人员,这里有一些心得,分享给你们但愿对你们有所帮助。
关于如何学习Matlab
个人学习方法很简单:Matlab是练出来的,而不是看出来的。不少人问我有没有比较好的Matlab教材,我说随便找一本吧,均可以。只要书里面有最基本的语法和命令,对于一个有编程基础的人,Matlab能够在一个下午的时间内学会。固然,仅仅是学会。若是想要对Matlab比较驾轻就熟,那么最好的办法就是练习。练习的素材不少,好比对于学经济学的,能够作一些simulation之类的,也能够试着把计量或者宏观教材里面的一些算法写写出来。一开始可能很慢,可是当你完成了一个比较大的project的时候,你的Matlab的功力将会有巨大的提高。
固然,在你写程序以前,多读一些别人写的好的code是很是有帮助的。
一些Matlab的经验
一、适当了解一些数值计算、数值分析以及最优化的理论
用Matlab的无非是作数值计算或者最优化,这也是Matlab的强项,Matlab有足够多的工具箱解决这些问题。可是在使用这些工具箱以前,应该首先了解一些数值计算以及最优化的理论。这一点在程序碰到问题或者计算结果不理想的时候尤其重要。不少时候结果不理想并非本身的理论出了问题,而是盲目或者错误使用Matlab的工具箱而致使的。好比我曾经作过一个单纯形法的优化程序,可是结果老是不理想,这个时候就要返回到单纯形法具体是一种什么样的算法来考虑这个问题,最后发现是因为目标函数的某一部分十分平缓致使的。
固然更重要的是若是你不理解理论,不少问题根本不知道如何处理。有个学化学同窗就曾问我一个程序怎么写,说matlab确定能够完成的。了解清楚以后才明白原来他想作的就是一个受限最小二乘。可是他不懂得什么是最小二乘(由于没怎么学过数学),固然面对这个问题无从下手。
二、理解Matlab中时间空间的转化
这个问题没有人强调,但我觉着蛮重要。这里的关键点其实很简单,就是尽可能减小重复计算,哪怕是多项式复杂度之内的计算。重复计算的内容应该适时保存到内存中,之后直接调用。一个程序可能会重复运行几千次几万次,一点点的浪费时间均可能被放大不少。空间(内存)咱们是能够扩充的,可是时间不是,因此绝大多数时候咱们须要放弃空间,得到时间上的迅捷。
这里有个故事,曾经在某技术论坛上看到的,说腾讯公司早期作的QQ实在太过垃圾,他们追踪过QQ的行为,发如今几分钟时间里重复调用了某同一注册表项几百次。显然注册表的内容所占内存是有限的,甚至是能够忽略的,可是每次读注册表项可能都要读硬盘,这里的时间花费是很大的,为何不把这项内容直接存储在内存里呢?
一个比较经典的例子:考虑交换两个变量a,b的值,有以下写法:
c=a;
a=b;
b=c;
或者:
a=a+b;
b=a-b;
a=a-b;
第一种写法多占了内存,由于须要多申请一个c的内存空间;第二种写法节省了内存空间,可是却多了三次计算时间。请问哪一种好?不必定,看你的时间空间的权衡。可是具体到这个例子来讲,第二种是不推荐的,由于:首先,第二种程序晦涩难懂,难以维护,内存不至于低到不能存储一个变量;第二,若是两个数字都特别特别大,计算a的时候会有溢出的危险。
三、造成良好的编程规范
我想几乎全部学过编程的人都被这样告诫过。比较好的是Matlab自带的编辑器自己就能够自动缩进之类的,程序十分易读。可是还有一些东西是有些人未曾注意过的。好比变量名,一个好的变量名必定要有清晰的含义,让人一看就能明白,不然往后的修改维护必然要花费更多的时间去识别这些变量名的含义。这一点能够参考http://coolshell.cn/articles/1038.html http://coolshell.cn/articles/1990.html 这里面详细列举了不少命名的规则和技巧。
还有一点就是注释。好的注释能够极大的方便之后的维护以及代码的重用。个人习惯是在代码的开头都要交代这个代码是干什么用的,怎么用等等。在程序中一个大块的功能模块也要加上注释告诉你们你在作什么。若是某个语句很复杂,能够加注释告诉你们这句到底在干什么。这样写出来的程序维护起来或者他人使用起来将很是方便。
另有一篇十分有趣的文章分享给你们:如何写出没法维护的代码 http://coolshell.cn/articles/4758.html
四、若是拿到一个任务而又没有思路,试着把问题分解或者转化。
之因此叫作程序,是由于咱们所作的工做就是告诉计算机要作什么,该怎么作。因此若是你的脑子里根本不知道这个问题该怎么解决的时候,你就更加没法写出程序。找思路的通常方法是分解问题,而后逐个击破。或者在特殊状况下,须要把问题转化。
分解与转化的第一步是把实际问题转化为数学问题。这一步可能已经作好,可能没有。若是没有,那么这一步就叫作数学建模。绝大多数问题均可以转化为两类问题,一类是最优化问题,一类是求解问题。若是你能知道你在最优化什么东西或者求解什么东西,问题就简单不少。
转化问题的第二步是把数学问题转化为程序(不是代码)。也就是说,你要想清楚这个问题(最优化或者求解)是怎么一步步实现的。 这个过程可能很简单,有现成的方法用,也有可能很复杂,还可能涉及多种转化。好比咱们经济学中遇到的求解动态最优化,常常要把连续的东西离散化(离散化很重要!)。
最后,考虑怎么把你的程序转化为真实的代码。这一步说简单很简单,由于只要你作好了以上两步,这一步是顺其天然的。可是固然会有不少小的细节,也许这就是所谓的technique。可是我仍是觉着,学习编程不是学习technique,而是学习第二步,虽然本文关注的更多的是technique。
五、若是程序出错了,而又查不到语法的错误,使用断点
编程中最可怕的错误不是语法,而是逻辑错误,由于逻辑错误是最难debug的。一个颇有用的工具就是断点。
断点应该是debug中最经常使用的工具。Matlab的编辑器中能够很方便的实现(在每一行的开头有个小横线,单击一下变成红点,而后就设置成断点了)。当程序运行到断点以后就会中断,而后会在主窗口显示K>>的标志,这时你能够输入命令查看内存状况等等。一步步的跟踪,直到变量值跟你的预期不同,这时你就能够很容易的找到错误在什么地方发生了。
六、若是试了不少办法仍是不能找到错误,那就尝试一下终极debug方法,适用于各类语言
真的有这么强大的debug方法么?有的!这个方法很简单,离开你的电脑,找一我的,随便什么人,说一遍你的程序的思路,说的越具体越好。多数状况下,你在阐述的过程当中,程序的错误就会忽然从你的大脑里冒出来了。
若是实在找不到就找大街上的乞讨人员吧,给他们十块钱他们应该很乐意听你说的,而且说不定还能够给你一些很好的建议,而后告诉你,十年前他们也在作一样的工做。
七、 理解通用与专用之间的权衡
你能够写一个通用的程序,也能够写一个专用的程序,这须要你的权衡。通常状况下,专用的程序你能够研究清楚其结构,从而找到最快的算法,而通用的程序则不能达到这点,由于要考虑到不少不少特殊的状况。
好比给定一个分布函数F(x),我想要写一个随机数生成器是的生成的随机数的分布函数为F(x). 方法很简单,先生成一个均匀分布的随机数a,是的a~U(0,1),而后计算F的反函数在a处的值。不少人可能会用fsolve之类的办法,可是这不是最快的。若是咱们已经知道F是一个单增的函数,那么这个解有且仅有一个。这样咱们就能够直接使用一些算法去解决他。
相似的问题还有若是咱们知道导数,那么求最优化最好的方法也许是牛顿法,而不是用单纯形法去寻找,那样既不精确又慢
可是通用的程序也是很是吸引人的,由于能够大大的减小开发的时间,若是计算时间不是首要考虑的问题的话。
八、尽可能使你的程序更通用
也就是说,尽可能使你的代码能被重复利用。这样能够节省不少写程序的时间,而你发现这些东西都是你写过不少遍的。
不少人没有一个写通用程序的好的习惯。好比说下面一个最简单的例子:
x=randn(10000,1);
y2=zeros(10000 ,1);
for i=1: 10000
y2(i)=exp(x(i));
end
这样写的问题在于,若是你的x须要改变了,好比改为100维,那么你须要修改不止一次。可是若是你写成这样:
x=randn(10000,1);
y2=zeros(length(x),1);
for i=1:length(x)
y2(i)=exp(x(i));
end
那么是否是仅仅修改一个地方就能够了呢?
九、 尽可能使你的程序模块化
把须要重复进行的程序尽可能写成函数,便于修改和维护。写成函数的好处是使你在同一时间只关注一个问题,可是若是你把全部的东西都放在一个程序里,你可能须要考虑的问题就不止一个了。
十、在使用变量以前先进行声明,尽可能少使用矩阵变维操做
这不是matlab必须的,可是是十分建议的。好比若是你写下了以下的代码:
for i=1:10000
y=y+i;
end
你没有声明y,而是直接试用了它,极可能会出现问题。好比你的内存里以前已经有y,y=10,那么你的计算结果是否是会大10呢?更有可能的状况是你以前已经运行了这个程序,可是你的开头没有clear(开头使用clear也是很好的习惯)
此外,尽可能少使用矩阵变维的操做。由于每次声明变量或者矩阵变维,Matlab总要申请一个新内存空间,频繁进行变维操做会很快侵蚀掉你的内存空间,这点在大矩阵的时候特别重要。
十一、计算尽可能多的使用矩阵,尽可能少的使用循环
循环的好处是比较容易想,比较容易些,可是也比较难以维护,最重要的,速度很慢。
好比下面一个例子:
x=randn(10000,1);
tic
y1=exp(x);
toc
tic
y2=zeros(length(x),1);
for i=1:length(x)
y2(i)=exp(x(i));
end
toc
输出结果:
Elapsed time is 0.000287 seconds.
Elapsed time is 0.000963 seconds.
可见使用矩阵比使用循环快了三倍。
十二、若是进行大量的重复操做,能够考虑使用并行计算
好比在作Monte Carlo模拟的时候,你的每次循环都是独立的(每次循环不影响下一次循环的结果),那么能够考虑使用并行处理,若是你的电脑是多核的。
首先,你要用如下命令建立几个并行的进程:
matlabpool local 4
其中4是你的计算机核心数。而后,使用parfor代替for循环就能够了。可是使用这个命令必定要注意使用前提和不要每次循环访问一样的可变的变量。
1三、尽可能少的涉及符号运算
Matlab最强大的是其数值运算能力,而不是符号运算。若是你须要处理诸如求导求极限之类的工做,用Mathematica或者Maple。特别是尽可能少的使用符号定义的函数, 好比用fsolve之类的,若是只是计算一次两次很是方便,可是若是进行大量重复的此类运算,其速度很慢,最好研究清楚要解的函数的性质,用专门的算法进行处理,matlab大多数时候也有专门的工具箱。
1四、压缩你的内存空间
Matlab的内存管理方式使得内存常常“碎片化”,特别是当一个变量被清除出内存,留下的空间又不足以装下下一个变量,内存就变成了“碎片”,这个跟硬盘碎片是一个道理。能够用"pack"命令。若是你的内存里面有很大的矩阵,不要忘了常常用"clear"命令清除不用的矩阵。固然pack命令比较耗时,不要再循环里面或者函数里面使用。还有一个办法就是先用save命令保存内存,而后所有清除掉,再用load命令载入。
1五、使用稀疏矩阵
若是碰到一个矩阵很大,可是多数数字都是0,试着用sparse命令转化为稀疏矩阵。一个例子是空间计量里面的权重矩阵,通常来讲多数是0,LeSage的空间计量工具箱里面就是用的稀疏矩阵
源地址: http://blog.renren.com/GetEntry.do?id=883297385&owner=222496841html