Matlab心得及學習方法(不斷更新)

Matlab心得及學習方法(不斷更新)

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

相關文章
相關標籤/搜索