Matlab心得及学习方法(不断更新)

Matlab心得及学习方法(不断更新)

Matlab心得及学习方法(不断更新)
P.S. 那些网上转载我的文章不写明出处的傻眼了吧?!老子更新了!

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

时间: 2024-08-09 19:54:11

Matlab心得及学习方法(不断更新)的相关文章

Android开发之应用程序更新实现

最近给项目app做升级,对Android应用程序更新稍有研究,分享一下我的心得. 既然是更新,那么一定是要联网和下载的,所以联网和存储访问权限时一定要有的: <!-- 权限申请 --> <uses-permission android:name="android.permission.INTERNET" /> <!-- 联网权限 --> <uses-permission android:name="android.permission

openwrt 基于qmi的 3G|4G拨号

简介 qmi -- Qualcom Message Interface 直译过来是 高通消息接口.顾名思义该接口的作用就是定义与高通设备(主要是modem)直接的通信消息. qmi英文完整资料如下: 因为最近在基于qmi开发一款mifi设备的3\4G拨号,所以最近我会把我在这一过程遇到的问题,和一些心得体会陆续的更新上来. 开发简介 依赖的驱动--qmi_wwan 该驱动在linux3.4以上的内核中默认支持了.对于通用的3/4G modem支持是没有问题的,但对于某些特殊的的modem是没有其

修改错误代码

前几天一直被一个错误迷糊得晕头转向,后来给别人看一下,问题顿时迎刃而解,也让自己颇有感悟. 修改错误一定要有正确·的逻辑思维,否则很容易陷进谜谭.看到错误,首先要分析系统给出的错误提示,然后根据错误提示,按照一定的顺序来修改代码.必要的时候可以添加一些功能来判断代码是否正常运行,但是又不能胡乱添加,一定要注意逻辑的正确性.必要的时候可以把修改方案一一列出来,一条条去分析,一个个的去排除错误.当然在无可奈何地情况下还是可以重建一个文件,说不定问题就解决了. 简单得写出我最近学习php的心得,随笔待

设计模式之 - 简单工厂模式(实例)

一个简单的计算器栗子,  计算值和结果是固定的, 运算过程是根据需求变化的. 工厂模式一般适用于: 若干具有相同父类的子类, 并且需要重复做一件事情的时候, 所以顾名思义叫做工厂模式, 重复的东西全让工厂做了~ 现在只是明白原理,但是还没真正在项目中实践过, 心得会不断的更新的 using UnityEngine; using System.Collections; public class Opration { public double NumberA{get;set;} public do

html伪类与伪元素选择器

什么是伪类: 伪类用于定义元素的特殊状态. 例如,它可用于: 当用户将鼠标悬停在元素上时为其设置样式 样式访问和未访问的链接不同 在获得焦点时设置元素的样式 伪类的用法:伪类:{ } 伪类的种类: /*链接伪类*/ 注意:link,:visited,:target是作用于链接元素的! :link 表示作为超链接,并指向一个未访问的地址的所有锚 :visited 表示作为超链接,并指向一个已访问的地址的所有锚 :target 代表一个特殊的元素,它的id是URI的片段标识符 /*动态伪类*/ 注意

高中生的IT之路-自序

近几年来越来越多的人问我关于 高中生要不要读大学.大学选择专业.毕业后的择业问题,索性我不如把我对这几方面的理解写出来,如果有幸能帮助到更多的人,那也算是个人对社会做出了一点贡献. 我高中毕业后并没有进入大学,而是直接进入到社会工作.刚进入社会的时候去餐厅当过服务员,后来又在朋友的帮助下进到一家IT公司进行实习生培训,再后来就正式进入到软件工程师的行业,从刚开始的门外汉通过自学 从实习生成为工程师.高级工程师.项目经理.技术经理,到现在在一家互联网公司任职技术经理的职位并且自己在经营一家餐饮公司

学习方法总结-实习心得

学习方法分享 1.提需求,找bug 上图是一个可以说从无到有的过程,再没有思考和发现这两方面问题时,不会存在后面去解决的方式. 思考问题的存在和发现自己需要什么是很关键的,可以理解为对自己提需求和从自身找bug. 2.多分享,多讨论,多思考 我非常热衷于听他人的分享,我认为这是快速提高的一种方式,很幸运我们团队在分享知识上做的很多. 分享和讨论会让思维发散,期间会有很多灵感去想到一些平常想不到的点. 通过这些不明白的问题,或者学习到他人解决问题的方法,总结沉淀下来会是很大的收获. 3.对JAVA

Matlab使用心得

1..*和*的区别 .*只能用于两个同型矩阵相乘,且是相对应的元素做乘法运算,其运算规则和我们线性代数里的乘法规则是不一样的:而*用于两个矩阵相乘,如mxn,nxk两个矩阵相乘,它的运算规则和线性代数里的一样. 2.reshape函数 利用向量创建矩阵 3.length()函数获取一维向量长度,若输入为矩阵或多维向量,则返回各个维尺寸中最大的. size()函数获取矩阵行列数. 4.稀疏矩阵(减少了存储空间) 稀疏矩阵可以直接和普通矩阵直接相加: 5.在指定路径创建文件夹 mkdir('e:\\

J2EE编程心得-使用Hibernate出现的错误及解决方法 更新中...

1.  使用Hibernate时出现Session was already closed异常 出现此异常的原因是Session已经被关闭 如果不是使用的SessionFactory.getSession()来获得Session. 而是使用SessionFactory.getCurrentSession()方法来获得Session时,当事务结束的时候,不管是提交还是回滚事务,hibernate会自动关闭Session的, 所以不需要手动关闭. public boolean insert(LiftI