95
MATLAB MATLAB MATLAB updated 2007.2

MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

  • Upload
    others

  • View
    6

  • Download
    0

Embed Size (px)

Citation preview

Page 1: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

MATLAB 的數學實驗從資料分析學 MATLAB 程式設計

從 MATLAB 程式設計瞭解統計

汪群超updated 2007.2

Page 2: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

2 MATLAB 的數學實驗

Page 3: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

目錄

序 4

再序: 不可變與不可不變: 我的程式寫作觀 7

1 從繪製函式圖認識 MATLAB 9

2 MATLAB程式的迴圈技巧: 以積分為例 21

3 MATLAB的副程式 31

4 簡單的演算法: 以計算方程式的根為例 37

5 演算法: 計算函數的極值 49

6 多變量函數之最小值 61

7 群組分類: 線性迴歸與最小平方法 71

8 群組分類: Nearest Neighbor Method 83

3

Page 4: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

4 MATLAB 的數學實驗

Page 5: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

如果學習數學相關的學科是痛苦的, 那真是一個天大的誤會。 數學長久以來被 『妖

魔』 化了。 在許多學生心中有一種無形的恐懼, 甚至厭惡。 有些人選擇提早擺脫數

學的糾纏, 但有些人卻一直揮之不去, 走到哪裡都會碰到數學, 或數學相關的話題

或應用的領域。

逃避未必求得正果, 逃避只是摀著眼睛假裝看不到,一切的逃避或美其名的以不感

興趣迴避, 都是錯把數學當成表皮摻有農藥的蘋果。 儘管知道裡面好吃, 卻不敢去

碰。 但數學能力對一個人的重要性不會因此消失。 因為數學能力的展現不一定用

來解決數學問題。 或許因為如此隱晦, 才會引導學生對數學的學習做出零和的決

定: 學或不學, 而且往往是一輩子的賭注。

這本單元式的講義企圖挽回一般學生對數學莫名的恐懼, 進而開始喜歡上它。 不

管你以前多麼痛恨數學, 從此刻起, 不計前嫌的再一次面對數學。 這一次讓電腦來

幫幫忙, 透過電腦程式的寫作去了解數學的內涵與精神。 數學題材不在深, 電腦程

式不在精闢, 一切都是玩票的。 學完後, 你不會成為電腦程式專家, 更不會變成數

學家, 但是你可能不再討厭數學, 且對電腦程式的運作有些概念。 或許不知不覺中,

數學與電腦會激盪出你未來求知求學的另一番憧憬。 幾句話充作參考

用電腦來解決數學問題, 比較輕易的化解對數學的厭惡與對電腦的恐懼。

用電腦來解決數學問題, 找不到答案也可以觀察到許多未知的領域。

用電腦來解決數學問題, 不知不覺中, 觀察、 解析問題的能力提昇了。

用電腦來解決數學問題, 時間似乎流逝的特別快, 你已經浸在裡面了。

用電腦來解決數學問題, 看問題的角度變大了、 變寬廣些了。

5

Page 6: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

6 MATLAB 的數學實驗

對數學的畏懼來自不當的教學或失敗者的恫嚇。 不了解其實學習數學是培養各種

領域專長的催化劑。 數學不見得是第一線的武器, 但它永遠是後勤的資源。 常常隱

而不見, 需要時, 卻自然流露。 不要小看數學的影響力, 它無所不在、 無孔不入, 你

只是沒有得到適當的引導!這本講義透過獨立單元介紹一些統計系學生會接觸到的

數學, 並結合數學軟體MATLAB, 將數學的內涵呈現在螢幕上。 這本講義的編排

方式不是朝向完整教科書的巨細靡遺, 僅作為上課練習的腳本與課後作業的參考,

上課的過程仍是必須的。 部分內容謫自同學的作品。 當學生的數學情緒被激發時,

我似乎看到潛藏在他們內心理面, 受到壓抑的數理能力, 他們的發現往往超過我的

預期。

汪群超

2002年7月於台北大學

Page 7: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

再序

不可變與不可不變: 我的程式寫作觀

教學七年了, 這本講義也用了三年。 其間經過多次的修改, 不管擴編還是刪減, 多

半是依據上課時學生的反應而來。 這本講義其實很多地方寫得不夠詳細, 本想進

一步將所有細節完整呈現, 成為一本書。 但幾經思量, 仍維持原貌, 原因是太詳細

的內容會養成學生的依賴心, 喪失原先期望學生自己去補足不清楚、 不詳細的部

分。 希望學生藉著這門課拾回過去學得不清不楚的微積分、 統計學與線性代數。

這本講義企圖將數學原理以電腦數據圖表的方式呈現出來, 再要求同學以文字圖

案呈現出其間的條理, 這樣的訓練是現今大學生十分欠缺的。 說穿了就是 「表達的

能力」 的培養。 這可不是說、 學、 逗、 唱之類的表達, 而是一種試圖將不易說清楚

或難以理解的東西, 透過文字、 圖表或語言將它交代清楚。 這樣的能力絕對需要長

時間的訓練, 有了這項 「絕技,」 大學畢業生不必急著說自己學非所用。 有太多的

事實證明, 擁有絕佳的表達能力, 放諸四海都餓不著肚子。

表達能力的養成必須按部就班,一點都急不得。 可惜的是, 莘莘學子不是自作聰明,

便是固執己見, 往往喜歡憑自己過去的經驗來解決未知的問題, 缺乏耐心去熟練不

熟悉的工具, 不願將專注力用在問題的觀察。 學習過程像極矇著雙眼亂砍亂殺, 到

頭來學不到東西還怪老師出太多怪怪的功課, 既對升學沒有幫助, 也無助以後做生

意賺大錢, 不多久便放棄了, 殊是可惜。 告訴他這是未來升官發財的利器, 他當你

在三娘教子, 在家裡聽多了。

以寫作程式為例, 每一種程式語言都有其語法規範, 該怎麼寫怎麼用, 一點也馬虎

不得, 連錯一點點都不行, 沒得商量的。 初學者往往輕忽之, 不喜歡被 「規範」 束

7

Page 8: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

8 MATLAB 的數學實驗

縛, 不顧老師一再地提醒, 愛怎麼寫就怎麼寫, 天才般的自己編撰起語法來了, 結

果當然是錯誤百出, 急得老師在一旁乾著急。 更有甚之, 錯了還不認帳, 直呼語法

太不人性化, 不能隨意更動, 學它何用, 便率性的打起電動或MSN 來了。

寫程式首要遵守語法教條, 待熟悉語法規範之後, 才能漸漸懂得運用, 透過寫一些

不痛不癢的小程式, 一方面熟悉語法, 一方面體驗其威力。 漸熟, 才慢慢從觀察別

人寫的 「模範程式」 中, 瞭解死的語言原來也能玩出活把戲, 這才一步步進入寫作

程式的精髓, 進一步玩出樂趣。 這道理亙古不變, 古今達人不管學習琴棋書畫, 還

是打拿摔跌等武藝, 無不遵循這樣的哲理1

能力未至不可變也、 學識未敷不得變也、 功侯未到不能變也。

學於師已窮其法, 不可不變也、 友古人已悉其意, 不得不變也、

師造化已盡其理, 不能不變也。

從 「不可變、」「不得變、」「不能變」, 到 「不可不變、」「不得不變、」「不能不變,」 可以

作為寫作程式的養成過程。 學習之初應謹慎遵循所有的規範, 一絲不苟, 不能濫用

自己的小聰明亂抄捷徑, 要聽話、 要服從, 將老師的交代與叮嚀當作聖旨般遵循,

務必做到。 如此這般一段時日之後, 犯錯愈少, 進步愈多, 自然而然當變則變, 逐

漸形成自己的風格。

不能急, 成就總在不知不覺中 「赫然」 被別人發現, 絕非刻意營造而能得。 別人眼

中看到的成就, 對自己而言永遠都是平常事而已, 只不過在許多小地方比別人好

一點點罷了。 但別小看這一點點, 許許多多的一點點累積起來, 那可有多少啊!

汪群超

2005年2月於台北大學

1謫自五絕奇人鄭曼青先生名著 「曼髯三論。」

Page 9: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

第 1 章

從繪製函式圖認識 MATLAB

能夠在畫面上看到繪製的數學函式, 可以拉進與數學間的疏離感。 如果能夠親自

動手操作電腦畫出在書本上曾經看過的函數圖形, 那會是件令人興奮的事。 本單

元試圖讓學生了解電腦繪製函式圖形的原理, 並藉此熟練 MATLAB 這個數學軟

體的特色, 特別是它的矩陣表示法。

本章將學到關於程式設計

變數的觀念與設定、MATLAB 的四則運算、 變數矩陣的索引、 函數的計算與繪圖

的觀念

〈本章關於 MATLAB 的指令與語法〉操作元 (operators): + - × / . ∧ : ;

指令:zeros, ones, eye, diag, plot, polyval, sin, cos, exp, sqrt,

nthroot, pi, set, xlabel, ylabel, title, grid

語法: 矩陣的建立

9

Page 10: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

10 MATLAB 的數學實驗

1.1 練習

MATLAB以描點法來繪圖。 所以對二維圖形而言, 必須先產生函式上對應的 (x,y)

點。 然後將這些點以符號的方式顯示在一定範圍的座標軸上。 下面的範例將協助

你成功的在 MATLAB 畫出一張簡單的圖。

範例1: 先練習如何在MATLAB 的環境下 (命令視窗) 建立矩陣 (含 scalar, vec-

tor and matrix)。 分別建立定義如下的 A,B,C,D,E,F,G,H,I,J,K 11個矩陣, 並

觀察結果。

輸入方式:

A = [1 2; 3 4] B = [1 2 3] C = [5 6 7 8]′ D = 1

E = C(1 : 2) F = C(3) G = A(1, 2) H = A(:, 1) I = A(2, :)

J = 0 : 5 K = −5 : 0.5 : 5

注意:

1. 在 MATLAB 的語法中, 上述代表矩陣的A, B, · · · , K稱為變數, 其內容

(值) 可以透過等號 (=) 右邊的資料賦予, 且隨時可以被改變。 請注意等號

右邊的資料可以是數值、 向量或矩陣資料, 或者也可以一律視為矩陣, 因不

管是數值或是向量都是矩陣的特殊型態。

2. 當變數被賦予內容後, 在命令視窗下輸入變數名稱, 將可顯示出其內容值。

3. 每個指令的最後若加上分號 (;), 則運算的結果將不會顯示在命令視窗上。

4. 請留意等號 (=) 右邊賦予矩陣資料時的符號 (, : ;), 從執行的結果去瞭解

其代表的意涵, 並記錄下來。

5. 變數E, F, G, H, I是取其他變數的部分內容, 請特別留意矩陣的索引方式

及結果, 對於往後 MATLAB 的使用非常關鍵。 MATLAB 的矩陣索引與

理論上一致, 指令A(i, j) 代表第 i (橫) 列, 第j(直) 行的元素, 如圖1.1

所示。 圖中A代表一個5 × 5的矩陣, 指令A(2, 3)代表第2列第3行的值, 也

Page 11: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

1. 從繪製函式圖認識 MATLAB 11

就是7。 MATLAB除提供與理論上相同的索引方式, 另可採一維的索引法,

圖中每個位置右下角的編號, 代表該矩陣一維的索引值, 所以指令A(12)與A(2, 3)會

得到相同的結果。

圖 1.1: MATLAB 的矩陣索引

此外,MATLAB 提供更多的索引方式, 方便擷取更多的資料, 圖1.1也顯

示擷取第5行的5種方式, 其中保留字’end’代表該行或該列的最後一個索引

位置, 方便下指令時不需要先知道矩陣的長度。 圖中也展示如何擷取一個

子矩陣。 不管是從矩陣中擷取一個值、 一個向量或是一個子矩陣, 初次接觸

的使用者, 不妨實際在命令視窗上逐一輸入, 並觀察結果, 對照指令, 相信

一定可以心領神會, 比起在此說得九彎十八拐要來得有用。 練習時, 可以指

令A = magic(5)來產生圖中的矩陣。

6. 利用 MATLAB 的指令 whos 觀察每個矩陣的大小。

7. MATLAB 也提供一些指令可以更迅速的產生特殊的矩陣, 試試看這些指

令:zeros, ones, eye, diag。 使用前可以利用 help 的指令了解使用的方式,

Page 12: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

12 MATLAB 的數學實驗

譬如 help zeros。

範例2:Let A = [1 2; 3 4], B = [5 6; 7 8], c = 3, 逐一執行以下的運算練習並

觀察結果。

A + B, A−B, A + c, A ∗B, A/B, A∧c, c ∗ A, A/c,

A. ∗B, A./B, A.∧c, A′, B′, (A ∗B)′, B′ ∗ A′

請注意 MATLAB 所使用的運算元符號, 如 +−∗ / ˆ . ′ 等所代表的意涵。 從執

行的結果去觀察並記錄下來。

MATLAB的數學四則運算與冪方大致符合學理上的矩陣運算, 但 MATLAB 也

巧妙的利用矩陣式的資料結構, 設計了一個特殊的運算元 (operator)”·”, 讓多筆

資料的運算可以一次完成, 譬如變數x, y各有5個樣本, 其值如下

x = [ x1 x2 x3 x4 x5 ], y = [ y1 y2 y3 y4 y5 ]

要計算兩變數的乘積xy的5樣本值,MATLAB 的指令為x · ∗y, 即

(x1 x2 x3 x4 x5

).∗︸ ︷︷ ︸

x

(y1 y2 y3 y4 y5

)︸ ︷︷ ︸y

=(

x1y1 x2y2 x3y3 x4y4 x5y5

)︸ ︷︷ ︸x.*y

一個指令同時計算好所有的樣本資料, 這有別一般正規的向量乘積, 必須注意前

後向量的大小才能相乘。 而 MATLAB 這種元素對元素的乘法 (element by el-

ement), 提供大量資料運算時的方便。 再舉矩陣的運算為例來區分 * 與 .*的差

別:

Page 13: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

1. 從繪製函式圖認識 MATLAB 13

a11 a12

a21 a22

︸ ︷︷ ︸A

b11 b12

b21 b22

︸ ︷︷ ︸

B

=

a11b11 + a12b21 a11b12 + a12b22

a21b11 + a22b21 a21b12 + a22b22

︸ ︷︷ ︸

A*B a11 a12

a21 a22

.∗

︸ ︷︷ ︸A

b11 b12

b21 b22

︸ ︷︷ ︸

B

=

a11b11 a12b12

a21b21 a22b22

︸ ︷︷ ︸

A.*B

除乘法外, 除法 (\) 與乘冪 (∧) 都可以這樣使用, 不管是向量或矩陣, 只要使用

的時機恰當, 都可以達到很好的效果。 以下的內容及單元將陸續透過實際的問題

介紹這個特殊運算元的好處。

範例3: 函式 y = f(x) = 2x + 1

1. 當 x = 0, 1, 2, · · · , 10, 分別計算其相對的函數值 y。

2. 繪製函式圖, 其中 0 ≤ x ≤ 10

利用簡單的四則運算, 函數值很容易計算出來, 如圖1.2。

圖 1.2: 函數運算

Page 14: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

14 MATLAB 的數學實驗

當重複執行這兩個指令並改變 x 值1, 便可以輕鬆的計算出所有的函數值。 不過每

次只算一個函數值絕不是強力軟體的作為,MATLAB 利用了矩陣的運算提供方

便的計算方式, 如圖1.3所示

圖 1.3: 以矩陣運算計算多個函數值。

從圖1.3中 x, y向量很清楚的呈現出其間的函數關係, 這些向量的對應數值形成

繪圖時的座標點, 以下說明繪製函數圖形的步驟:

1. 先依繪圖範圍產生 x 方向的所有點, 譬如 x = 0 : 10

2. 再根據函式的關係計算所有相對應 y 方向的座標值, 譬如:y = 2 ∗ x + 1

3. 再利用指令 plot 繪製不同型態的圖形, 譬如plot(x, y) 將所有的座標點以

直線連接。 請特別注意 plot 提供的各種繪圖的選項 (利用 help plot 或

doc plot), 試著去改變描繪座標點的方式、 點的符號、 顏色等選項。

範例4: 繪製函式

1Tips: 由於必須不斷的帶入不同的 x 值, 相同的指令必須不斷的被執行, 如果要重複的輸入

指令, 將影響實驗的興致。 所幸在 MATLAB 的命令視窗中可以利用鍵盤中的 ↑ 鍵, 不斷的將之

前執行過的指令秀出來, 方便實驗的進行。 例如要重複圖1.2的指令, 可以按兩次↑ 鍵回到 x = 0,將 0 修改為 1, 按 「Enter」 執行該指令, 隨後再按兩次 ↑ 鍵回到 y = 2∗x+1, 直接按 「Enter」執行便可以得到答案。

Page 15: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

1. 從繪製函式圖認識 MATLAB 15

1. y = f(x) = x2 + 3x + 5 −5 ≤ x ≤ 5

2. y = f(x) = x3 − 10x2 + 29x− 20 0 ≤ x ≤ 7

前一個範例說明繪製函數圖形的三個步驟, 缺一不可, 也各有 「訣竅」, 否則不是畫

錯就是畫得不好看, 展現不出 「一張圖值千字」 的價值。 對初學者而言, 應先學會

利用 MATLAB 的特點來計算函數值, 特別是 MATLAB 特殊的運算元”·”。 例

如計算第一個函數值時, 可以先試試 x2 的計算方式, 待結果正確了才加入其他較

簡單的項次 (3x + 5), 圖1.4展示平方項的計算。

圖 1.4: 函數中計算平方項次的方法。

繪圖的方式同前一題, 不過須注意

1. 描繪的座標點 「數」; 前一個範例的函數是一條直線, 當 plot 指令將座標點

與點間以直線連接時, 看起來毫無問題, 但是當函數為曲線圖形時, 座標點

的距離如果不夠近, 兩點間的直線連接將會造成圖形的鋸齒狀, 不符合函數

的特質, 因此需要利用更密集的座標點來產生平滑的視覺效果。 這需要從 x

軸資料的產生做起, 譬如 x = 0 : 0.1 : 7, 從 0 到 7 每隔 0.1 產生一個點,

而點與點間 0.1 的間距是否可以造成平滑的曲線端視視覺感受而定, 過小

並無意義, 徒增資料量與計算時間。 圖1.5展示不同間距的視覺效果。

Page 16: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

16 MATLAB 的數學實驗

圖 1.5: 座標點的間距

2. 指令 plot(x, y) 中, 變數 x 與 y 分別代表函數的 X,Y 座標點, 其值

的產生也不同。 變數 x 的內容依據繪圖的範圍與座標點的間距設定一組向

量, 如前述的x = 0 : 0.1 : 7, 而變數 y 的內容則依函數的關係從變

數 x 計算得來, 本題的函數具平方與立方項, 可以利用前一個範例陳述的

運算元 ” · ” 來做乘冪, 一次計算所有 x 座標的對應函數值 y。 譬如指

令:y = x.∧2 + 3 ∗ x + 5, 在此x.∧2的意義請參考範例1、2的矩陣運算。 如

果只是單純的使用x∧2,MATLAB 將出現錯誤的訊息, 告知

圖 1.6: MATLAB 指令執行的錯誤訊息

表示只有方陣 (含數值) 才能做平方, 一般向量的平方是不合法的。

3. 當函數是多項式時,MATLAB 提供一個簡便的指令 polyval, 方便計算多

項式的函數值, 下列的指令可以取代之前的函數計算:

Page 17: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

1. 從繪製函式圖認識 MATLAB 17

x=-5:0.1:5;

p=[1 3 5]; 多項式函數的係數

y=polyval(p,x);

關於 polyval 的詳細使用方式, 請參考線上使用手冊的說明。

範例5: 繪製函式 y = f(x) = x4 − 8x3 + 16x2 − 2x + 8

請選擇適當的範圍, 務必看到比較完整的圖。

函數圖的繪製範圍的選取非常重要, 太寬、 太窄、 偏左或偏右都可能看不到該函數

的全貌或特質。 譬如畫出像圖1.7的函數圖, 便因為範圍取得太寬, 以致於看不到

該函數 「最有價值」 的最小值部分, 因此繪圖時必須不斷的調整範圍, 以突顯出函

數最值得觀察的部分。

圖 1.7: 函數圖範圍的決定

Page 18: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

18 MATLAB 的數學實驗

範例6: 依下列範圍繪製函式 f(x) = x + sin(x)

(1) 1 ≤ x ≤ 1000 (2) 1 ≤ x ≤ 500 (3) 1 ≤ x ≤ 100 (4) 1 ≤ x ≤ 10

這個範例也是說明範圍選擇的重要, 透過不斷的縮小範圍, 才能看出函數的特性。

1.2 觀察

1. 電腦繪圖係以描點的方式畫上去, 因此點與點間的距離越近, 所呈現出來的

圖形越平滑。 請觀察在一定的範圍內, 點的數量多與少的效果, 也就是調整

x 的間距。

2. 利用 MATLAB 指令計算所畫上去的點數 (即觀察向量變數 x 的長度)。

譬如 length, size 等指令。

3. 改變 plot 指令的參數, 讓畫上去的點做不同的表現, 譬如, 畫出散佈圖。 利

用 help plot 指令, 看看有那些繪圖的技巧可以使用。

4. x 軸的範圍取捨非常重要, 除了給定的範圍外, 請試試看其他範圍。 寬一點

或窄一點。

5. 為這些圖加上些裝飾, 如 x , y 軸的文字、 標題或是格線等等,e.g. xlabel,

ylabel, title, grid。 例如圖1.7展示 title 的使用, 其指令如下

title(′f(x) = x4 − 8x3 + 16x2 − 2x + 8′)

請注意 title 所顯示的是文字而非函數的計算, 因此與 MATLAB 的運算

元無關, 純粹是文字的編輯, 譬如符號 ∧代表文字的上標。 相關的用法可以

查循線上使用手冊。

Page 19: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

1. 從繪製函式圖認識 MATLAB 19

6. 練習將結果 (圖) 貼到 WORD 或其他文書編輯工具 (如 Latex 或中文的

cwTex) 裡面, 做好如何呈現結果的工作。 將 MATLAB 產生的圖形貼到其

他地方的方式有兩種; (1) 利用 File/Export(7.0版以前) 或 Save As(7.0

版以後) 的方式將圖形以檔案的方式儲存下來。 (2) 利用 Edit/Copy Fig-

ure 的方式將圖形 copy 下來, 再到 WORD 或其他類似的軟體, 直接以

paste 的方式貼回。

1.3 作業

畫出下列函式,x範圍自訂, 盡量畫出比較完整的函式圖, 並加上必要的裝飾文字。

。 未曾使用過的指令, 請自行利用 help 或 doc 該指令的方式察看其使用說明。

1. y = f(x) = sin(x) + cos(x), 代表sin, cos的指令分別是sin, cos

2. y = f(x) = 1− e−2x

1 + e−2x 代表指數的指令 exp

3. y = f(x) = 3

√4− x3

1 + x2

開根號的方式有兩種, 譬如計算√

9 的指令可以是:(1) 以冪方的方式 9∧0.5,

(2) 採開平方根的指令sqrt(9),(3) 採開實數根的指令 nthroot(9, 2)。2

第1與第3個方式均適用於本題函數, 當使用冪方時須特別注意 MATLAB

冪方指令的下達方式, 譬如指令 −8∧(1/3)及(−8)∧(1/3)會產生不同的結

果, 何者才是正確的, 從結果很容易辨識, 但卻與一般常理的認知相左, 因此

建議除平方根外, 還是採nthroot指令比較安全, 否則一旦錯誤將很難發現。

4. y = f(x) = 1

x− 1

5. y = f(x) = 1

2√

2πe−(x−1)2

8 π 的指令為 pi

6. y = f(x) = x2/3 =3√

x2

2這個指令在7.x 版之後才有。

Page 20: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

20 MATLAB 的數學實驗

7. y = f(x) = 2x3 − x4

8. y = f(x) = x√

4− x2

補充: 下面的指令可以改善圖形呈現的品質

x = 0 : 0.5 : 5;

y = x.∧2 + 2 ∗ x + 3;

plot(x,y) 此時出現的 x 軸刻度間隔為 0.5, 下列指令可以將間隔改

為 1

set(gca,’xtick’,0:1:5) 當然將 ’xtick’改為’ytick’就可以針對 Y

如果想將線條變粗, 使用

plot(x,y,’LineWidth’,2)

裡面的2代表線條得寬度, 數字越大越寬。 如果還想配上顏色, 可以這樣做

plot(x,y,’LineWidth’,2,’color’,’red’)

MATLAB的繪圖指令非常豐富, 變化很多, 可以從線上使用手冊查詢到。 不過對

初學者而言, 實無須浪費過多時間在這方面, 看到一個學一個, 夠用就好, 不急於

一時, 隨著時間的累積, 將會非常可觀。 另一個簡便的方式是直接在繪圖區作圖形

的編輯, 利用滑鼠選取欲編輯的物件 (線條、 符號、 或是區域), 左鍵按按、 右鍵試

試, 將發現很多編輯的選項, 多試幾次便會。

Page 21: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

第 2 章

MATLAB程式的迴圈技巧: 以積分為例

迴圈技巧是程式語言的生命, 有了它程式才顯示出價值。 電腦之應用貴在於能大

量且快速的執行相同的計算, 而迴圈便是這項功能的靈魂。 MATLAB 程式的迴

圈技巧與其他語言類似, 甚至相同, 有其他語言基礎的可以很快的進入狀況。 本單

元利用計算積分的數值方法來介紹 MATLAB 中迴圈的使用。

本章將學到關於程式設計

MATLAB的程式結構、 程式的邏輯概念與程式檔案的管理。

〈本章關於 MATLAB 的指令與語法〉操作元 (operators): .∧ ./

指令: for, tic, toc, area, factorial, trapz, quad, pause

語法: for 迴圈的建立與技巧。

21

Page 22: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

22 MATLAB 的數學實驗

2.1 背景介紹

函數的定積分∫ b

af(x)dx可以解釋為函數圖形在直線x = a及x = b之間與 x 軸

所圍的面積, 如圖2.1所示的陰影面積。

圖 2.1: 積分的幾何意義

這個不規則形的面積也可以所謂的黎曼積分來定義, 適用於數值積分的計算:

黎曼積分(Riemann Integral) 的定義:

將一個閉區間[a, b]任意分割成 n 個小區間, 其分割點為 a < x1 < x2 <

· · · < xn−1 < b, 這些小區間的寬度表示為 4x1,4x2, · · · ,4xn。 這個

數值n∑

k=1

f(xk)4xk

稱為函數f(x)在這些區間的的黎曼和 (Riemann Sum)。 當區間寬

度4xk → 0時

limn→∞

n∑k=1

f(xk)4xk

稱為函數f(x)在區間[a, b]的黎曼積分。

一般定積分的數值計算上多應用黎曼積分的觀念, 本單元的探討以此為基礎。 為

Page 23: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

2. MATLAB程式的迴圈技巧: 以積分為例 23

方便說明本單元內容, 以下均假設所有小區間的寬度4xk一致, 即

h = 4xk =b− a

n

黎曼和寫成

n∑k=1

f(xk)h =n∑

k=1

f(a + kh)h (2.1)

代表n個長方形的面積和。 圖2.2是這黎曼和的示意圖。 當 h 越小時 (n越大), 陰

影部分的長方形越窄, 也因此上緣越貼近函數的曲線。 當 h 趨近於0時 (n →∞),

這無限多個長方形的面積和即為黎曼積分。

圖 2.2: 積分的定義: 黎曼和

2.2 練習

範例1: 利用上述黎曼和公式(2.1), 寫一隻程式計算

∫ 3

0

x + 3 dx

Page 24: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

24 MATLAB 的數學實驗

其中設 h = 1。 請比較黎曼和與實際的積分值。 如果設 h = 0.5, 結果又如何?

當h = 0.25是不是更接近了呢?

當 h 值愈趨近0時, 數值計算的黎曼和將與實際值愈接近, 不過程式的寫作越麻

煩, 因為要加入的長方形面積越多。 下一個範例將介紹 MATLAB 的迴圈技巧,

將可有效且迅速這個不方便。

範例2:『迴圈技術』(for loop) 可以輕易解決這個問題。 先練習迴圈技巧: 寫一支迴

圈程式計算1加到100。 程式執行時要在每個迴圈中印出累加值及迴圈數。

迴圈的指令為 for,請利用 help 找出迴圈的使用方法, 下表的示範程式計算 「從1加

到10」。

total=0; 註: 必須先將 「總和變數」total 的值預設為0

for i=1:10 註: 迴圈開始

total=total+i; 註: 開始累加, 變數 total 值每次都不同

end 註: 迴圈結束

total 註: 印出結果

在上述的範例中嘗試將第一行拿掉, 看看執行結果有何差別。 將一行程式暫時拿

掉的方式, 是將其變為註解行, 即在最前面加上百分比符號%。 另外, 寫迴圈程式

有個慣例, 在迴圈開始的第一行與最後一行間的程式碼做適當的縮排。 這樣做的

原因除方便除錯外, 也讓增加程式的可讀性。

Tips: 學習程式寫作最好的方法是參考正確的示範程式, 在瞭解語意後, 多模仿,

久之, 便能得心應手。 在模仿上述程式片段前, 初學者最好先找出迴圈指令 for 的

正確語法, 再逐行解讀示範程式, 完全瞭解後, 最後執行示範程式並觀察結果。

範例3: 利用迴圈技術計算範例1的數值積分值, 假設 h=0.01、0.001時。

Page 25: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

2. MATLAB程式的迴圈技巧: 以積分為例 25

利用迴圈的方式, 可以順利解決累加的問題, 但你是否發現當h愈小時, 所花費的

計算時間愈多。 別忘了 MATLAB 的專長, 為避免過多的迴圈造成較差的執行效

率, 請利用矩陣的乘法解決累加的問題, 並比較與迴圈技術在計算時間上的差別

(h 愈小差別愈明顯)。 計算程式執行時間, 參考時間指令:tic, toc, 例如

範例: 計算∑5

x=1(x + 3)

程式: tic

x=1:5;

answer=sum(x+3)

t=toc %顯示自 tic 後的執行時間

Tips: 程式語言的邏輯與數學或一般生活邏輯有些差異, 因此寫程式時, 千萬別

一口氣寫完才執行, 這樣會造成除錯上的困難, 徒浪費不必要的時間。 對初學者而

言, 也不需要從第一行開始寫起, 可以先寫中間的主體部分或甚至後面的結果, 再

逐一根據指令或變數的需求穿插補足。 過程中, 可以隨時儲存程式並執行, 確定每

個指令與變數的使用都是正確的。

範例4: 計算定積分

∫ 5

−5

x2 + 3x + 5 dx

的黎曼和。 建議先畫出函數圖形, 再利用迴圈法與矩陣法分別計算積分值。

所謂矩陣法就是不使用迴圈的方式, 利用向量矩陣的方式直接計算每塊長方形的

面積, 並加總得到面積和。

範例5: 如果能畫出積分計算過程的長方形, 會有助於對積分計算的瞭解? 試試看

能不能利用迴圈的技巧, 沿著函數的曲線, 畫滿一排長方形。 至於長方形的寬度可

以從程式來控制。

Page 26: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

26 MATLAB 的數學實驗

為 MATLAB 圖上的曲線塗上顏色的方式如下:

x=[4 6]; 註: 準備兩個點的值畫一條直線

y=[5 5];

area(x,y) 註:area 與 plot 的不同在於塗色

axis([0 10 0 10]) 註: 改變座標範圍方便觀察

最後一個指令 axis 用來改變圖形的座標範圍,MATLAB 自行決定範圍有時並不

符實際的要求, 矩陣裡的四個數字分別代表 [xmin xmax ymin ymax], 其意義

如字面所示。 當利用迴圈技術計算面積並繪出面積圖時, 由於電腦速度的關係, 感

覺上好像每塊面積是同時畫上去的, 實際上並非如此。 此時可以利用 pause 指令

來緩和速度, 強迫電腦停止運作或停止一定的時間, 譬如在 area(x,y) 後面加上

pause(1);

強迫電腦停止 1 秒鐘, 在迴圈裡面呈現出來的效果有如動畫般的神奇。 不妨試著

結合前一個範例積分程式, 配合塗上顏色與時間暫停, 玩玩動畫。

範例6: 如上題, 將每個小面積從長方形改為梯形, 如圖2.3, 並改寫黎曼和的數值

定義 (2.1), 重新計算一次。 另一方面, 請嘗試逐漸降低 h 值, 觀察計算的結果, 與

前面長方形面積有何不同? 兩個公式孰優孰劣?

數值積分的相關計算方法很多, 其中的 「辛普森法則 Simpson’s Rule」 比梯形法

更為準確。 同學有空不妨去找找看什麼是 「辛普森法則」。 另外,MATLAB 提供哪

些計算積分的指令呢? 採用什麼樣的計算法則呢? 查查看, 並試著用來計算前面

幾個範例的積分式。

2.3 觀察

1. 數值積分與數值導數一樣都面臨一個h值的選擇, 但兩者間還是有所不同。

h值對數值積分的影響的關鍵因素在哪兒? 與數值導數有很大的不同喔!

Page 27: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

2. MATLAB程式的迴圈技巧: 以積分為例 27

圖 2.3: 梯形面積的黎曼和

2. 長方形面積的黎曼和有三種選擇方式,

• 其一, 長方形範圍超過曲線, 面積總合將超積分值。

• 其二, 長方形範圍在曲線下面, 面積和低於積分值。

• 其三, 長方形範圍介於上述兩種之間。 這個方法與梯形法的面積是否

較為接近?

2.4 作業

1. 改寫黎曼和定義 (2.1), 成為梯形的面積和。

2. 利用長方形面積的黎曼和計算∫ 5

−5x3 + 2x2 + 3x + 4 dx 並畫出長方形面

積,h 值設定為 0.5。

3. 畫一張圖比較 『長方形』 法與 『梯形』 法的準確度。 任選一個積分函數與範

圍。 要怎麼畫? 怎麼比較請自行決定!

4. 寫一支程式採梯形法計算下列的積分: 程式盡量具彈性, 可以讓使用者自行

決定上、 下限。 最好先將圖形畫出來。

Page 28: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

28 MATLAB 的數學實驗

•∫ 5

0100exdx (ans: 14741.32)

•∫ 7

0x2e−xdx (ans:1.94),Gamma 分配

•∫ 1.96

−1.961√2π

e−x2

2 dx

5. 已知 p(θ|y) 為一概似函數, 其中 y 及 θ 分別為樣本與未知參數。 假設

p(θ|y) = (2 + θ)125(1− θ)38θ34

p(θ) = 1, 0 ≤ θ ≤ 1

計算後驗機率的期望值 (即 θ 的貝氏估計) E(θ|y), 即計算

E(θ|y) =

∫ 1

0(2 + θ)125(1− θ)38θ34θdθ∫ 1

0(2 + θ)125(1− θ)38θ34dθ

6. 還記得泰勒展開式 (Taylor Expansion or Taylor Series) 嗎? 任何函數

都可以展開成一個無限的級數。 例如: 函數f(x)在常數a展開之泰勒級數

f(x) = f(a)+f ′(a)(x−a)+f ′′(a)

2!(x−a)2+· · ·+f (n)(a)

n!(x−a)n+· · ·

當f(x)是一個比較複雜函數 (譬如無理函數) 時, 這個無限級數的展開式

便可以派上用場。 適當的選擇a及無限級數的前幾項, 往往可以得到滿意的

近似值。 譬如當a = 0時, 這個無限級數變成一個簡單的多項式, 當需計

算f(x)的值時, 便可以用前述的近似方法, 以簡單的計算得到滿意的近似

值。 這個練習將以迴圈的方式將泰勒級數的前幾項一一加起來。 請按下列

步驟計算f(x) = ex(譬如 f(2))

• 選擇一個適當的a值, 將函數展開。 哪一個a值比較有利計算呢?

• 挑好a值後, 到底要加幾項才能得到比較滿意的近似值呢? 請建立一

個迴圈, 設定20圈, 每繞一圈加一項進來並列印出加總的結果 (即逐

圈列印結果)。

• MATLAB 中計算指數函數的指令是 exp。 本題試圖以泰勒展開式計

算指數函數, 一此程式中不可使用指令 exp 。

Page 29: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

2. MATLAB程式的迴圈技巧: 以積分為例 29

註: 計算階乘, 參考指令 factorial。

7. 計算積分還有一種方式叫做 「Monte Carlo Integration,」 其原理簡單敘

述如后,

∫D

f(x)dx =

∫D

f(x)

p(x)p(x)dx = E

[f(x)

p(x)

]其中p(x)被當作機率密度函數 (pdf), 積分的問題於是可以寫成函數的期

望值。 在決定 pdf 函數p(x)後, 可以利用抽樣的方式, 取出相當數量的樣本,

再以樣本計算函數值f(x)/p(x)及其平均數來近似期望值。 其準確度與p(x)的

選擇、 樣本數大小都有關係。 當然, 當樣本數趨近無限大時, 不論選擇的p(x)為

何, 總能逼近完美的積分值。 但適當的選擇卻可以以較少的樣本得到最準確

的結果。 原則上p(x)的選擇與接近函數f(x)的外形為佳。

利用此法, 重做作業4的積分問題, 需說明使用的p(x)與樣本數, 譬如計算∫ 7

0f(x)dx, 當選擇均等分配為其 pdf 函數時, 問題變成

∫ 7

0

f(x)dx = E

[f(x)

17

]= 7E [f(x)] =

7

N

N∑k=1

f(xk)

其中 xk 為樣本,N為樣本數。

Page 30: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

30 MATLAB 的數學實驗

Page 31: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

第 3 章

MATLAB的副程式

副程式 (function) 的應用在一般程式語言裡非常的普遍, 幾乎是必備的技巧, 只

要稍具複雜度的程式多半會使用到副程式。 當程式出現重複的程式片段, 或是該程

式片段過長, 佔據過多篇幅, 妨礙了程式的流暢與可讀性時, 可以將該程式片段移

出, 另置他處 (在同一程式檔案或其他檔案), 稱為副程式或子程式 (subroutine)。

副程式除了可以減少主程式的程式碼, 提高主程式的可讀性外, 有時候也可以供其

他程式呼叫, 提高程式寫作的效率與一致性。 另外 MATLAB 在 7.0版以後新增

「匿名函數」 功能, 減輕副程式的帶來的檔案管理問題, 對於小型的副程式提供更

簡潔的作法。

本章將學到關於程式設計

MATLAB的程副式與匿名函數的結構與應用。

〈本章關於 MATLAB 的指令與語法〉指令:function

31

Page 32: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

32 MATLAB 的數學實驗

3.1 背景介紹

主程式與副程式間的 「溝通」 靠參數的傳遞來聯繫。 主程式將一些既定的參數傳給

副程式作為程式執行所需的變數, 副程式執行完畢, 將結果以一組參數傳回給主程

式。 副程式的角色相當於主程式的 「協力廠商,」 主程式將部分工作 「outsource」

出去給副程式做。 而副程式扮演 「協力廠商」 的角色, 通常只做些單純的工作, 因

此可以設計成為更 「通用」、 為更多的 「主程式」 服務。

副程式的結構隨程式語言的不同有些差異, 請參考 MATLAB 對於副程式的定

義, 以下舉個簡單的範例說明 MATLAB 副程式的結構與使用方式:

副程式:stats.m

function [mu,sigma]=stats(x)

mu = mean(x); %計算平均值並且放入輸出變數 mu

sigma = std(x); %計算標準差並且放入輸出變數 sigma

主程式:main.m

x=chi2rnd(2,1,100); %產生任意的資料

[mu, sigma] = stats(x); %呼叫副程式 stats, 並且傳入一個資料參數 x,

%傳回結果放在 mu 及 sigma 的變數裡面。

供後續程式使用。

通常副程式的函數名稱 (function name) 與檔名相同。 一般而言一個副程式檔案

內含一個副程式, 但必要的時候, 也可以超過一個副程式, 副程式之間彼此呼叫。

此外, 副程式與主程式間溝通的管道靠輸入與輸出變數, 其個數是需要都可以超過

一個, 當然個數太多時, 寫起來很冗長不方便, 可以考慮採結構性 (structure) 的

變數, 彈性也更大。 關於結構性的變數如何設定與使用, 請參考手冊。

另外, 副程式的執行過程與主程式完全不相干, 變數名稱也可以不同, 輸入與輸出

變數依出現的次序為對應關係, 並非依變數名稱。 在副程式內的任何變數也是獨

立的, 與主程式無關, 並不影響主程式的變數或命令視窗的變數。

Page 33: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

3. MATLAB的副程式 33

3.2 練習

範例1: 寫一支程式分別自 「常態」、「卡方」 與 「二項」 分配的母體中抽取100樣本,

並分別計算其 「樣本均數」、「標準差」、「中位數」、「最大值」 及 「最小值」。 其中計算

的部分模仿上述的副程式, 加以擴充即可。

上述的範例是副程式使用的典型, 其優點讓主程式看起來比較 「乾淨清爽,」 也可

以提供不同的程式呼叫。 另一種副程式的使用時機如範例1的積分函數所示:

範例2: 使用MATLAB 提供計算數值積分的指令quad, 計算∫ 2

0sin(x)dx。

其使用方式有以下三種典型:

方式1 方式2 方式3quad(′sin′, 0, 2) F = inline(′sin(x)′); quad(@my int fun, 0, 2);

quad(F, 0, 2);

其中方式3,@之後的my int fun代表一個副程式的名稱。 該副程式寫成:

function y=my int fun(x)y=sin(x);

上述三個方式中, 方式1與2適用於當欲積分的函數很單純時。 若函數複雜, 以副

程式的方式來描述積分函數是比較恰當, 甚至是唯一的方式。 MATLAB 在7.0版

以後, 提出 「匿名函數」(anonymous function) 的方式, 免除副程式需要建立一

個檔案的麻煩, 卻可以提供重複使用的方便性, 類似上述方式2的作法, 但更具彈

性。 以上述的積分為例, 寫成

f=@(x)sin(x);

quad(f,0,2);

Page 34: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

34 MATLAB 的數學實驗

f 代表 sin 函數, 也可以拿來計算函數值, 譬如, f(pi/2) 計算 sin(π/2)。

試試看以下稍複雜些的積分式。

範例3: 模仿範例2的三種方式分別計算:

•∫ 5

0100exdx (ans: 14741.32)

•∫ 7

0x2e−xdx (ans::1.94)

•∫ 1.96

−1.961√2π

e−x2

2 dx

3.3 觀察

1. 副程式的使用除了解決程式碼重複的問題外, 也提供一個可重複使用 (re-

useable) 的程式, 提供給別的程式呼叫。 但副程式的本身也製造出管理的

問題, 太多的副程式往往讓程式設計師本身迷航了。 所以什麼樣的程式碼適

合編成獨立的副程式, 必須認真思考, 包括長度, 可重複使用的頻率。 如果

不合乎這些法則, 寧願還是以程式碼的方式存在原程式中。

2. MATLAB 自6.5版後加入 「程式加速」 的機制, 在合乎某些條件下, 即使

使用多層的迴圈 (for loop), MATLAB 的加速機制依舊可以適當的轉換

程式碼, 加速程式的執行。 不過副程式的呼叫卻違背這些條件, 讓加速機制

失效。 因此, 當程式的執行時間很關鍵, 或是程式耗費太多時間, 都要考慮

限制副程式的使用。

3.4 作業

1. 將之前寫過計算多項式微分的程式改成副程式的結構, 使其使用上像呼叫

MATLAB 的指令。

2. 將之前寫過多項式積分的程式改成副程式的結構, 使其使用上像呼叫 MAT-

LAB 的指令。

Page 35: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

3. MATLAB的副程式 35

3. 寫一個標準的副程式, 專用來計算多項式的函數值 (功能像polyval)。 輸入

參數定義為多項式的係數。

Page 36: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

36 MATLAB 的數學實驗

Page 37: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

第 4 章

簡單的演算法: 以計算方程式的根為例

求解

f(x) = 0

計算方程式的根已經是老問題了, 不過卻是一個頗不簡單的問題。 多年來各路英

雄好漢提出各式各樣的方法, 針對不同的函數, 用紙筆推導或應用電腦及數值的

方法。 特別當電腦的速度逐漸提昇, 許多紙筆很難推導或甚至解不出來的問題, 慢

慢在數值方法的演進中得到解決。 本單元介紹MATLAB計算方程式根的指令與

使用方法, 如 roots 及 fzero。 另外是幾個著名的演算法, 如牛頓法、 堪根法及定

點法, 都是計算方程式根的典範。

本章將學到關於程式設計

演算法的程式寫作、 迴圈中斷的技巧、 程式偵錯(Debug) 的技巧及副程式與匿名

函數的應用。

〈本章關於 MATLAB 的指令與語法〉指令:roots, fzero, while, break, quad

語法: 無限迴圈的寫法

37

Page 38: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

38 MATLAB 的數學實驗

4.1 背景介紹

有些方程式的解可以透過數學的技巧推導出結果 (closed-form solution), 但有

很多方程式根本寫不出完整的解。 譬如: 求解

x− e−x/2 = 0

於是開始衍生以迭代法 (iteration) 的觀念, 逐步求解, 在牛頓的時代便已經有這

樣的觀念與做法。 不過受限於人力所能演算的能力, 往往祇能解決一些相對簡單

的方程式。 複雜一些, 或函式的計算比較難的問題, 直到電腦運算能力提昇, 才得

到解決。 而電腦取代人手, 只是以極快速度重複迭代的過程。 但如何迭代? 如何判

斷是否為根? 何時停止迭代? 是否重根? 如何找到所有的根? 這些問題還是要回

到紙筆的推導。 不過不再是推導出完整的解, 而是退而求其次的, 去推導如何找到

近似解的方法 (或稱演算法 algorithm)。 凡事從簡單的入手, 假設要求解

f(x) = x2 − 3x + 2 = 0 (4.1)

這是一個有完整解 (closed-form solution) 的方程式, 可以透過數學求解的技巧

找到答案。 不過在此, 我們將透過數值的演算方法及電腦程式來解決。

以數值演算法求解的方法很多, 牛頓法是其中的代表, 是以遞迴迭代的方法求解

的典型。 其步驟假設x0是任一的x值, 從x0開始, 到x1, x2, · · ·逐步往方程式的某

個根移動。 牛頓法定義了 「步伐」 移動的方式:

x1 = x0 −f(x0)

f ′(x0)

或者寫成,

xk+1 = xk −f(xk)

f ′(xk), k = 0, 1, 2, · · · (4.2)

透過圖4.1可以清楚瞭解牛頓法的原理。 跟著牛頓法的腳步, 很清楚的發現移動的

方向 (−f(xk)/f′(xk))一定是朝向方程式的某一個根。至於要移動多少步才能到

達 「目的地,」 在正確的執行程式後, 不難發現與初始值的選擇及函數的 「樣子」 有

Page 39: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

4. 簡單的演算法: 以計算方程式的根為例 39

關。 以下的練習將協助初學者慢慢的探討這類演算法的過程。

圖 4.1: 以牛頓法求方程式的根

4.2 練習

範例1: 寫一支程式, 按牛頓法的移動方式,計算方程式(4.1) 的根。 從初始值 x0 =

3.5 開始, 計算到第三步 x3 , 並逐步列印出每一步的 x 與 f(x) 值。

觀察 x1, x2, x3 是否逐漸往其中的一個根逼近 (或說 f(x) 是否愈趨近 0 )? 本

範例之初始值 x0 = 3.5 位在所有根的右方, 當初始值改為 −1(在所有根的左邊)

時, 移動的方向是否改變了呢? 是否也是朝著某個根呢? 如果初始值選在兩個根

的中間, 下一步會朝那個方向移動呢? 不妨實際試試看。

多項式的根一般而言相對的單純,MATLAB 提供的指令 roots 可以直接計算多

項式方程式所有的根, 以本範例為例, 指令如下

Page 40: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

40 MATLAB 的數學實驗

p = [1 − 3 2] %多項式的係數

roots(p) %呼叫 roots

範例2: 由於牛頓法的每個 「步伐」 的計算方式是固定的, 加上到達 「目的地」 的

步數不同, 程式的寫作上必須利用迴圈的方式, 重複同樣的動作。 請改寫範例1的

程式, 以迴圈的方式讓 xk 從 k = 0, 1, 2, · · · 不斷的遞迴迭代, 每個迴圈走一步。

程式中遞迴迭代的方式是典型的程式設計技巧。 由於程式中不可能維護 x0, x1, · · ·這樣不知確定數量的變數, 且後面的值由前一個產生, 在程式設計上通常只用兩個

變數配合迴圈來運作, 下面的程式片段說明這個技巧。

xk = initial value %先給定初始值, 迴圈中則代表現值

for i = 1 : N %開始迭代迴圈...

xk1 = xk − · · · %根據牛頓法從現值計算新值

...xk = xk1 %進行下一步前, 新值換成現值。

end

範例3: 延續上一個範例, 將求解的過程逐步畫出來, 如圖4.1所示。 不但將x0, x1, x2, · · ·一一畫出, 連同過程中的切線 (切線方程式先以紙筆導出適當的公式, 再放入程式

中) 也要畫出來。 每條線或每個文字畫完之後可以利用 pause(秒數) 的指令讓過

程呈現暫停數秒的效果。 否則以現在電腦的速度, 眼睛還來不及反應的瞬間, 圖上

所有的內容都畫好了, 看不出 「過程」 與收斂的情況。

在圖上將演算過程畫出來是件令人興奮的事, 可以清楚的觀察到演算法的演進, 提

高對數學的興趣。 不過卻是要一步一步來, 譬如圖4.1上的垂直線、 切線, 甚至

x0, x1, x2 的文字, 都要仔細琢磨, 一個個畫上去。 首先必須先確定程式大致上沒

問題, 再簡單的畫上 x 的演進過程並在圖上標示出位置, 譬如,

text(x, y,′X ′) %在座標 (x,y) 處畫上文字符號 X

圖4.2展示這個作法, 在演算的迴圈裡面執行上述指令 (當然得使用正確的 x, y

變數)。 成功之後, 再慢慢加上垂直線及切線。

Page 41: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

4. 簡單的演算法: 以計算方程式的根為例 41

圖 4.2: 演算過程的註記

4.3 觀察

1. 以演算法求解通常面臨 『何時停止演算』 的問題, 否則程式會繼續下去, 沒

完沒了, 也就是迴圈的 「圈數」 如何決定。 不過剛開始可以先將迴圈數設大

一點, 再觀察程式, 大約在演算多少迴圈後答案會趨於 『穩定』?

2. 迴圈指令除了 for 之外, while 是另一個常用的方式, 他的優點是不涉及迴

圈數的決定。 有關 while 的用法, 請自行參考 help 的範例。

3. 即便是先不知道迴圈依然可以使用 for 指令, 只不過要設定大一點。 然後迴

圈內必須做出跳出迴圈的條件判斷, 當條件滿足時, 利用 break 指令跳出

迴圈。 譬如:

Page 42: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

42 MATLAB 的數學實驗

for i = 1 : 10000 %開始迭代迴圈...

if 條件判斷式 %判斷式否已經到達目的地

break; %跳出迴圈

end...

end

4. 在逐步迭代的演算法中, 設定停止點或迴圈的中斷點是必要的, 否則迭代的

過程將無止盡的進行。 什麼時候該停止迭代呢? 換句話說, 該如何決定已

經到達目的地, 找到根了呢? 是在第k + 1步的函數值f(xk+1)很接近0, 還

是f(xk+1) ≈ f(xk), 或是xk+1 ≈ xk? 哪一個比較恰當? 與方程式有關

嗎? 上述程式中的 「條件判斷式」 便是依這些原則來判斷式否該終止迭代,

找到答案 (根)。 試著在演算法裡面訂一個停止點。

5. 演算法通常也面臨 『起始值』 的選擇問題。 有時候起始值的選擇是有根據

的, 但有時候卻是盲目的!試試看不同起始值, 是否會得到不同的答案 (根)?

6. 通常我們會從圖形去取得適當的起始值, 不過實際的狀況可能連圖都畫不

出來。 無法先透過圖形的判斷取得起始值。 想想看有沒有一些簡單有效的

方法, 可以讓程式自動找尋好的起始值? 譬如

while 1 %開始無限迴圈迴圈

ab = unifrnd(N1, N2, 1, 2) %在(N1, N2)的範圍內隨意找兩個值

a = ab(1); b = ab(2);fa = f(a); %計算函數值

fb = f(b); %計算函數值

if fa ∗ fb < 0 %判斷 a 與 b 之間是否存在一個根

break; %跳出迴圈

end...

end

xk = (a + b)/2; %初始值

Page 43: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

4. 簡單的演算法: 以計算方程式的根為例 43

圖4.3展示這樣的概念。 這個方式保證可以找到一個不太離譜的初始值 (最

壞的情況就是a與b距離很遠, 且其中一個離根很近), 但也有機會落在根的

附近。 這個方式如果能進一步改良, 讓(a+ b)/2不會離根太遠, 甚至還可以

逐步 「夾擊」 進逼到根的位置。 想想看、 試試看有哪些作法。

圖 4.3: 自動搜尋初始值的概念

7. 當方程式有重根時, 如何把所有的根都找出來呢?

8. MATLAB 除提供計算多項式方程式根的指令 roots 外,fzero 是另一個方

式, 其做法與之前學過的積分指令 quad 類似。 1 以下舉幾個使用方式, 計

算方程式 (4.1) 的根。

1fzero 或 quad 等指令在 MATLAB 7.x 版有不同於 6.x 版的作法, 更具彈性, 本範例以

7.x 版為主

Page 44: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

44 MATLAB 的數學實驗

方式1 %適用6.x 以上

fzero(′x∧2− 3 ∗ x + 2′, 2) %第2個參數代表計算在2附近的根

方式2 %適用7.x 以上

fzero(@(x)x∧2− 3 ∗ x + 2, 2);

方式3 %適用7.x 以上

f = @(x)x∧2− 3 ∗ x + 2; % 使用匿名函數 (anonymous function)fzero(f, 2);

以上幾個方式適用在函數比較單純, 可以一行指令表示者。 若函數複雜, 最

好還是以副程式 (函數) 的方式比較周延, 譬如以下的範例

fzero(@(x)myfun(x), 2)

其中呼叫的副程式如下

function y = myfun(x)

y = x∧2− 3 ∗ x + 2;

MATLAB 7.x 以上還可以允許輸入額外的參數到副程式中, 讓計算根的

功能更具彈性, 譬如

p = [1 − 3 2] %多項式的係數

fzero(@(x)myfun(x, p), 2)

其中的呼叫的副程式如下

function y = myfun(x, p)

y = p(1) ∗ x∧2 + p(2) ∗ x + p(3);

以上的範例說明當變更變數 p 時, 可以計算任何二項式方程式的根。這個程

式當然可以被改寫, 擴充為可以針對任何多項式函數。 此外,MATLAB 7.x

Page 45: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

4. 簡單的演算法: 以計算方程式的根為例 45

提供一種 nested function 的概念, 將一個副程式隱含在另一個副程式裡

面, 避免使用過多的程式, 這個功能類似前一個範例使用的匿名函數。 看看

這個新的作法:

p = [1 − 3 2] %多項式的係數

findzero(p, 2) % 呼叫副程式 findzero 計算2附近的根

副程式 findzero

function y = findzero(p, x0)

y = fzero(@(x)myfun(x, p), x0);

function f = myfun(x, p)

f = p(1) ∗ x∧2 + p(2) ∗ x + p(3);

end

end

依這個方式, 不難寫出與 roots 相同功能的副程式, 有興趣者不妨一試。

9. 解方程式的方法很多, 除本單元介紹的之外, 其他如 「割線法、」「定點法」...

等, 都值得去找來研究, 以增加自己程式寫作的能力。 其中的 「定點法」 很

有趣, 將 f(x) = 0 改寫成 g(x) = x, 以迴圈的方式迭代, 當近似根在

|g′(x)| < 1 範圍內均可以收斂。 有趣的地方在 g(x) = x 可已有許多種寫

法, 有些滿足收斂條件, 有些則否。 適當的選擇往往可以讓很棘手的問題變

得簡單, 扮演小兵力大功的角色。

以解方程式 f(x) = x− e−x/2 = 0 為例, 定點法將之改寫為

x = e−x/2 = g(x)

其幾何意義如圖4.4的斜線 (y = x) 與曲線 (y = g(x)), 其根為兩線的交

點。 利用定點法的 「定點意義,」 以迭代的方式

xk+1 = g(xk)

Page 46: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

46 MATLAB 的數學實驗

圖 4.4: 定點法計算根的過程

當 |g′(xo)| < 1 時, xk+1 將收斂到方程式根 xo。 圖4.4左圖展示迭代的過

程, 確實逐步往交點逼近, 右圖放大交點附近區域, 更容易看清楚收斂的情

形。

10. 牛頓法 (6.3) 並不保證收斂, 在某些情況下, 也會出狀況; 譬如,計算 f(x) =

x3 − 5x 的根, 若選擇初始值為 x = 1, 將發生震盪現象, 不論迴圈進行多

少遍,x 值始終在 1 及 −1來回交替。 不妨試試看, 觀察這個有趣的現象。

4.4 作業

1. 從圖4.1牛頓法的步驟, 推導出式 (6.3) 的方向,dk = − f(xk)f ′(xk)

2. 試寫出牛頓法計算方程式根的演匴法步驟。

3. 方程式

f(x) = −x + e−x/2 = 0

• 在適當的範圍內畫出圖形。

• 應用牛頓法計算方程式的根。

• 將程式設計成可以秀出求解過程的演進。(即標示出x0, x1, x2, · · · )。

4. 試寫出勘根法計算方程式根的演算法步驟。

5. 利用圖4.3勘根法的概念, 寫程式尋找上一題方程式的解。

Page 47: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

4. 簡單的演算法: 以計算方程式的根為例 47

6. 利用 MATLAB 指令fzero求上述方程式的解。

7. 利用定點法計算上述方程式的解。

8. 利用 MATLAB 的 fzero 與 quad 求出下列方程式的解 x。

0.9 =

∫ x

−∞

1√2π

e−θ2

2 dθ

注意:−∞ 在數值計算上並不可行, 可以試著以一個相當的數字代替, 譬如

−10。

Page 48: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

48 MATLAB 的數學實驗

Page 49: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

第 5 章

演算法: 計算函數的極值

計算函數的極值 (最大值或最小值) 一直是數學的應用上常見的問題, 其應用範圍

非常廣泛, 幾乎涵蓋理工、 商學的所有領域, 在微積分的教材中也是典型的範例,

而統計學中最大概似值 (Maximum likelihood) 的計算也是一例。 一般而言, 極

值的計算還是從函數的導數開始, 求其一次導數為零的根, 不過當函數本身的微

分很困難或甚至函數本身都不可得時, 數值演算 (numerical methods) 的方法

就顯得重要。 本練習將只針對簡單的函數做練習, 並與函數圖形配合, 了解數值計

算的方法、 精神與一些細節。 待熟練後, 複雜的函數也可以依樣畫葫蘆。

本章將學到關於程式設計

演算法的程式寫作、 迴圈中斷的技巧與匿名函數的應用。

〈本章關於 MATLAB 的指令與語法〉指令:min, polyder, roots, fminbnd, inline

49

Page 50: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

50 MATLAB 的數學實驗

5.1 背景介紹

假設函數為

f(x) = x4 − 8x3 + 16x2 − 2x + 8 (5.1)

如圖5.1所示, 該函數包括一個區域 (local) 最大值、 一個區域最小值及一個全域

(global) 最小值。 計算函數之極值通常先求其一次導數的根, 相當於函數斜率為

零的位置, 也就是圖形中波峰或波谷的位置, 或說區域極值 (local extreme) 的

位置。 當某區域極值實為所有極值之最時, 稱為全域極值。 極值分最大與最小, 可

從其二次導數的正負區別之。

圖 5.1: 函數的極值

一個函數的極值如果可以透過紙筆演算得到答案, 即所謂的 analytical solution

或 closed-form solution, 自然不需以電腦的數值方法解決, 所得到的答案當然

是完美的。 但是當函數複雜或囿於數學演算能力之不足, 便需要藉助電腦以其快

速的計算能力, 配合事先定義好的演算法則, 找到那些甚至連函數圖形都畫不出

來的極值 (函數繪圖的極限是兩個變數。) 雖然通常必須犧牲完美精準的答案, 但

在可接受的範圍內, 也算是不得已的良策。 本單元利用上述簡單的多項式函數, 介

紹利用演算法計算極值的一個典型。 觀念很簡單, 但透過電腦強大的計算能力, 其

威力無窮, 再複雜的問題也常能迎刃而解。

Page 51: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

5. 演算法: 計算函數的極值 51

電腦畢竟不如人腦, 可以拐彎抹角的思考。 利用電腦解決複雜問題時, 需要給予明

確的步驟指示, 讓電腦按部就班的執行。 這些步驟一般稱為演算法 (algorithm),

定義電腦從何處開始、 如何執行及何時結束。 演算法也可以說是寫程式前的前置

步驟, 程式的細節不在此表達, 只是點出精神與方向。 以下舉出典型的計算區域最

小值的演算步驟:

1. 找一個起始值 x1, 並計算 f(x1)

2. 在第k步 (已知xk), 計算 xk+1, 使得 f(xk+1) < f(xk), 其中k =1, 2, · · ·

3. 重複步驟 2, 直到|f(xk+1)− f(xk)| < ε

其中ε為一預設的、 通常很小的誤差值 (譬如 10−5)。 其值的大小需依函數的不

同調整, 有時候也會使用相對的誤差值, 即標準化的值, 如

|f(xk+1)− f(xk)||f(xk)|

< ε

上述的演算法的精神為

從函數的一個已知的點去找下一個比它低的點, 直到谷

底。

看來簡單, 其實變化很大, 尤其在步驟2對於如何找尋 『下一個低點,』 更是可以衍

生出許多的方法。 演算法只是提綱挈領, 其細節則是變化萬千。 簡單的說, 如何在

步驟2的xk位置, 找到下一個點xk+1 使得f(xk+1) < f(xk), 即

xk+1 = xk + dk, k = 1, 2, · · ·

dk代表從xk移動的方向, 其 『正負』 與 『大小』 代表移動的 『方向』 與 『距離』。 關

於dk 的選擇, 以下是一些建議:(請透過作業瞭解其正當性)

• dk = −f ′(xk)

Page 52: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

52 MATLAB 的數學實驗

圖 5.2: steepest descent 的移動方向

• dk = − f ′(xk)f ′′(xk)

dk = −f ′(xk)選擇了朝著 「負斜率」 的方向, 從函數圖來看, 那是一個 「下坡」 的

方向, 如圖5.2所示。這個選擇一般稱為 steepest descent。 當斜率為0代表到達了

山谷 (最小值),xk便不再移動。 第二個選擇則是加進了二次導數的影響, 稱為牛頓

法。 在理論上, 其往最小值移動的速度比 steepest descent 快, 值得玩味的是, 二

次導數的正負還會影響移動的方向。 不管如何, 還是先寫程式試看看這兩個dk的

移動速度與方向。

5.2 練習

範例1: 求極值的方法很多, 對於單純如式(5.1) 的單一變數函數,Direct Search(或

稱 Grid Search) 是個直覺的可行方式。 它是利用將一定範圍的實數軸分割成等

距的格子點 (grids), 分別計算每個格子點對應的函數值, 最後再從中挑選最小者

Page 53: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

5. 演算法: 計算函數的極值 53

當作是函數的最小值。 試著利用這個方法估計函數 (5.1) 的最小值。

所有 X 軸上格子點的函數值計算類似之前的單元介紹函數圖的描點繪製法, 最後

以 MATLAB 指令 min 來搜尋函數的最小值, 作法如下:

p = [1 − 8 16 − 2 8];

x = −1 : 0.00001 : 5;

y = polyval(p, x);

[Y, I] = min(y); % I代表最小值所在的索引位置

global min ds = x(I) %最小值為 Y , 發生在 x = x(I)。

很明顯的, 最小值的準確度與格子的 「粗細」 相關, 當然間隔太細, 計算量變大, 但

在電腦速度日益倍增的情況下, 這個方法也不錯。 請注意第四行 min 的用法, 其

中結果 Y 代表向量 y 裡面所有元素的最小值, 而 I則代表最小值出現的位置。 利

用這個位置找到相對應的 x 值 (第五行)。

範例2: 求極值的方法很多, 可採計算一次導數為零的方程式的根, 也就是前一個

單元的演算法則。 先將函數的一次導數寫出來, 再套入前一個單元的程式即可。 這

個方法適用於一次導數, 甚至二次導數 (求方程式的根也需要做一次導數) 已知的

情況下。 請利用指令roots 計算函數 (5.1) 的最小值。

作法如下

p = [1 − 8 16 − 2 8]; % f(x) 的係數

pp = polyder(p); % f’(x) 的係數

r = roots(pp); % f’(x)=0的根

[Y, I] = min(polyval(p, r));

global min roots = r(I)

其中 polyder 可以從多項式的係數產生其一次導數的係數。 利用多項式一次導數

的係數配合 roots 指令, 找出多項式導數為零的位置 ( x 值), 再利用 min 指令

Page 54: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

54 MATLAB 的數學實驗

找出最小的函數值。

在從事一件新的嘗試前, 最好從簡單已知的開始。 在將之前的演算法以程式來表

達前, 先知道答案會對程式的除錯與判斷有幫助。 待程式可以解決這個已知的簡

單問題時, 再慢慢擴大到比較複雜且未知答案的問題上, 千萬別急著一開始便挑

戰複雜度高的問題, 那無疑是找自己的麻煩, 對於程式寫作能力的提升也沒有幫

助, 卻是一般初學者常犯的毛病, 切記!切記! 這個簡單的範例與程式提供一個好

的開始。

範例3:MATLAB 也提供了 fminbnd 計算非線性函數的最小值, 試著計算函數

(5.1) 的最小值。

作法如下:

以下適合 MATLAB 7.x 版以上

p = [1 − 8 16 − 2 8]; % f(x) 的係數

global min fmin = fminbnd(@(x)polyval(p, x),−1, 5)%

在[−1, 5]的範圍內找最小值

以下適合 MATLAB 7.x 版以前

p = [1 − 8 16 − 2 8];

f = inline(′x∧4− 8 ∗ x∧3 + 16 ∗ x∧2− 2 ∗ x + 8′);

global min fmin = fminbnd(f,−1, 5)

未來在應用上盡量使用現成的指令, 以節省時間。 不過現成指令畢竟受限使用的

範圍, 不可能兼顧所有狀況 (函數), 必要還是得運用本單元介紹的演算方法。

範例4: 應用上述的演算法,寫程式計算函數(5.1) 的一個區域最小值。 先嘗試dk =

−f ′(xk)的選擇, 看看是否朝著目標前進。 成功了, 再試著採用牛頓法的方向。 能

成功的找到一個極值之後, 是否也能找到另一個? 初始值的決定是否影響所找到

Page 55: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

5. 演算法: 計算函數的極值 55

的極值, 都值得細細的觀察與一再的試驗。

程式的寫作宜從簡而繁, 由陋而精。 在過程中, 必須經常測試, 最好列印出過程的

中間值或畫圖來看看程式是否正確 (如圖5.3)。 然後才逐步修正往精簡路線調整。

換句話說, 先求正確, 再求精美。 如此一來, 程式的執行出了狀況, 才知道是程式

寫錯了、 還是演算法搞錯了、 或是觀念還不清楚。 如果都不清楚、 不能掌握, 就只

能兩手一攤, 無力回天。

圖 5.3: 牛頓法尋找區域最小值的過程

當實際採用上述的dk進行最小值的逼近時, 有時候無法收斂到區域的最小值, 反而

是發散出去、 或發生在兩點間震盪、 或甚至收斂到區域的最大值去了。 最常見的情

況是, 移動方向對了, 可是步伐卻太大了。 本該往低處移動的, 卻 「一飛沖天」 反

而到高處去了。 因此為了調節dk, 保證往低處移, 在下一個點的選擇採下列的 「管

制措施」

Page 56: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

56 MATLAB 的數學實驗

xk+1 = xk + βdk

β有時被稱為 『步伐調節器』。選擇適當的β值 (通常0 < β < 1), 以確保f(xk+1) <

f(xk), 甚至當β > 1時還可以加速收斂的速度。

β值對於步伐的調節常扮演重要的角色。 程式是否收斂或收斂的快慢與β的選擇息

息相關。 關於β的選擇非常多樣, 最簡單是所謂的 bi− section法。 也就是:

β = (1

2)α α = 0, 1, 2, · · ·

即一開始β = 1代表走一個dk的距離, 如果發現太大步 (f(xk+1) > f(xk)), 則

改走1/2個dk的距離, 再檢查一次, 如果還太大步, 則改走1/4個dk的距離, 以此類

推逐步減半縮回, 直到滿意為止 (f(xk+1) < f(xk))。

β的選擇讓每次都縮回原來的一半, 因此稱為bi − section法。 另外, 也可以選擇

一個奇妙的數字

β = (

√5− 1

2)α α = 0, 1, 2, · · ·

(√

5 − 1)/2稱為黃金比例 (Golden Ratio), 這個選擇也許沒太多道理, 既然縮

回來可以按1/2的比例, 為什麼不能是神奇的黃金比例呢? 試試看, 它是否展現神

奇的效果。

範例5: 利用匿名函數的方式繪製函數

f(x) = 2e−x sin(2πx)− 0.5 − 1 < x < 1

作法如下:

x=-1:0.01:1;

f=@(x)2*exp(-x).*sin(2*pi*x)-0.5;

plot(x,f(x))

Page 57: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

5. 演算法: 計算函數的極值 57

當自己寫程式利用各種演算法計算極值時,經常需要計算函數值 (Objective Func-

tion)。 如果該函數比較龐雜, 指令寫起來往往冗長, 又需要重複放在程式的不同

地方。 這對一個有經驗有訓練的程式員而言是痛苦不堪且看不下去的方式, 因此

常會採用副程式的方式來專門計算該函數值。 但這又製造另一個麻煩, 就是多一

個檔案要維護。 這時候 MATLAB7.x 提出的匿名函數便顯得可愛許多。 同樣是

一條指令, 清爽乾淨, 但不需費心去建立及維護一個新檔案, 畢竟檔案管理也是程

式員要去關心與在意的。

5.3 觀察

1. 一個函數的極值通常區分為兩種: 區域性 (local) 及全域性 (global)。 換

句話說, 函數圖形上的 『波峰』 與 『波谷』 都是極值所在。 一般的應用通常

是找所有峰頂的最高或所有谷底的最低, 也就是全域極值。 但目前對於全域

極值計算的相關演算法通常無法擺脫區域極值。 這是一個幾乎無解的題目,

目前大部分的研究都還是很依賴從該問題的本身尋求其他線索。 單純從數

學的角度來看, 對於函數本身較為 『崎嶇』 的問題而言, 大概找不到萬無一

失的解法。

2. 試試你寫好的程式, 從不同的起始點出發, 看看得到的答案是否不同。 其實

許多難解的問題最後都是依靠一個好的起始值才順利找到極值。 起始值的

選擇對某些函數而言並不重要, 但對某些函數卻很 『敏感』。 特別是想找到

全域極值的問題, 一個好的起始值是成功的一半。 通常起始值的選擇會從問

題本身的特性去找尋。 如何選擇好的起始值也是很重要的研究課題, 特別當

演算法本身已經無能為力時。

3. 不論是 steepest descent 或是牛頓法的移動方向, 都有其限制 (見作業),

並不能保證一定移往極值的方向。 一些調整的手段是必要, 特別當函數比較

特殊或是變數增多時, 更是常見。 本單元並不討論這些問題, 有興趣者很容

易可以找到相關的研究議題。

4. 演算法中經常要設定迴圈的停止條件; 譬如, 當找到 「滿意」 的最佳值時, 或

「步伐」 調整到 「可以接受」 的情況, 否則將按一定的法則繼續演算下去。 在

Page 58: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

58 MATLAB 的數學實驗

上述的練習中建議的條件為

|f(xk+1)− f(xk)||f(xk)|

< ε

是當函數f隨著x的改變已經呈現 「穩定」 的時候, 則可以假設已到達 「谷

底」 的最佳值。 但某些函數在接近 「谷底」 時, 呈現非常 「平坦」 的趨勢,

函數值變化很微小, 看似已接近谷底, 其實還有一大段距離, 如圖5.4所示,

當x值從4移動到6時,f改變還是非常小。 若使用上述的停止條件, 容易停在

「半路」 誤以為已到谷底。 遇到這樣的情況, 停止條件可以作適當的調整, 譬

如改以x值的變化作為是否到達谷底的依據,

|xk+1 − xk||xk|

< ε

圖 5.4: 當函數的極值位於 「平坦」 區域時

5. 「步伐調整器」β的加入使得程式必須在原有的迴圈內再加上一個 「內迴圈。」

以下的程式片段可以做為參考

Page 59: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

5. 演算法: 計算函數的極值 59

N = 10; %設定最多縮回來10次

beta = 0.5.∧(0 : N − 1); %設定 N 個縮回的比例,for · · · % 從1到0.5的 N-1次方

...for j = 1 : N %內迴圈, 負責步伐的調整,

... %逐次縮回直到滿意

xk1 = xk + beta(j) ∗ dk %步伐調整...if · · · %設定是否滿意的條件,

end %如果滿足則跳出內迴圈。...

end

上述程式中, 內迴圈的迴圈數N預設為10, 表示最多退回10次, 對於某些函

數而言並不恰當。 適當的調整或乾脆放大一點都是實務上的作法。

5.4 作業

1. 將之前介紹的演算法更詳細的寫出來, 包括把xk+1明確的表示出來, 並加入

步伐調整器β的選擇及跳出迴圈的條件。

2. 寫一支程式求f(x) = x4 − 8x3 + 16x2 − 2x + 8的幾個區域極值。(注意

起始值的選擇)。 將過程的演進表達出來, 譬如將數字1, 2, 3, · · ·寫在函數圖

上 (如圖5.3利用 text 指令), 代表x1, x2, x3, · · ·的位置。 執行中更可以利

用 pause(秒數) 來觀察程式走勢。

3. 自行找一個非多項式的函數, 利用 fzero,fminbnd 及本單元介紹的 Steep-

est Descent 等方法, 分別計算其最小值。

4. 關於dk = −f ′(xk)的選擇, 可以從下列的泰勒展開式得到

f(xk+1) = f(xk + dk) = f(xk) + f ′(xk)dk + O(d2k)

假設dk夠小, 足以忽略d2k以後的項目, 請證實 dk = −f ′(xk) 的選擇可以

保證 f(xk+1) 比 f(xk) 低。

Page 60: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

60 MATLAB 的數學實驗

5. 同上的泰勒展開式, 但多取一項 (忽略d3k以後的項目)

f(xk+1) = f(xk + dk) = f(xk) + f ′(xk)dk +f ′′(xk)d

2k

2!+ O(d3

k)

證明

mindk

f(xk+1)

的解為

dk = − f ′(xk)

f ′′(xk)

6. (optional) 限制式極值 (Constraint Optimization): 計算下列函數的極

小值

f(x) = 2e−x sin(2πx)− 0.5 − 1 < x < 1

本章並未針對限制式極值做任何討論, 在沒有參考任何書籍前, 不妨自己試

著想想看, 嘗試些直覺的方法, 最後再求諸關於限制式極值的做法。 千萬別

急著找參考資料, 這會阻斷自己思考的機會, 無法進一步提升解決問題的能

力。

Page 61: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

第 6 章

多變量函數之最小值

許多的應用問題, 如最大概似函數的參數估計, 最後都要計算多變量函數的最小

值。1之前的單元也介紹過單一變數函數的最小值演算法, 本單元將之擴展到多個

變數, 並介紹著名的 Newton-Raphson method及簡潔的 Steepest Descent

method。

本章將學到關於程式設計

演算法的程式寫作、 立體圖形的繪製技巧及MATLAB 圖形工具的使用。

〈本章關於 MATLAB 的指令與語法〉指令:meshgrid, mesh, surf,contour, colorbar, fminsearch, optimset

1最大值與最大值的計算被視為同一個問題, 其差別只是目標函數的符號而已。

61

Page 62: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

62 MATLAB 的數學實驗

6.1 背景介紹

多變量函數的最小值的問題表示如下:

minx

f(x) (6.1)

其中函數f(x) : Rn → R, 假設為可做二次微分的連續函數, 並且為變數x的非

線性函數。 譬如圖6.1是兩個變量的函數圖, 有一個最小值在底部的凹陷處。

圖 6.1: 兩個變量的函數圖

計算f(x) 最小值的必要條件為

5f(x) =

∂f(x)∂x1

∂f(x)∂x2

...∂f(x)∂xn

= 0 (6.2)

Page 63: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

6. 多變量函數之最小值 63

由於f(x)的非線性關係, 上式為一組非線性的聯立方程式,通常推導不出所謂的closed-

form solution。 因此必須藉助演算法的迭代方式逐步找到最小值。 例如

xk+1 = xk + dk k = 0, 1, 2, · · ·

在選擇一個適當的初始值x0後, 透過適當的 「方向」(dk) 調整, 一步步的逼近最小

值。 其中最負盛名的 「方向」 選擇為 Newton-Raphson method, 其法則如下:

dk = −(52f(xk))−1 5 f(xk) (6.3)

其中n×1的向量5f(xk)稱為梯度向量 (Gradient Vector), 而52f(x)為一n×n的對稱性矩陣, 一般稱為 Hessian matrix, 在此並假設其反矩陣存在, 其定義如

52f(x) =

∂2f(x)∂x1∂x1

∂2f(x)∂x1∂x2

· · · ∂2f(x)∂x1∂xn

∂2f(x)∂x2∂x1

∂2f(x)∂x2∂x2

· · · ∂2f(x)∂x2∂xn

......

. . ....

∂2f(x)∂xn∂x1

∂2f(x)∂xn∂x2

· · · ∂2f(x)∂xn∂xn

(6.4)

由於 Hessian matrix 牽涉到非線性函數的二次微分, 在某些情況下並不容易推

導或因反矩陣的計算上有困難 (或不存在), 因此出現了許多 「改良」 型的方式, 試

圖避開這些問題。 其中最簡單, 卻也非常有效的一個替代方案: 朝梯度向量的反方

向前進, 即

dk = −5 f(x) (6.5)

一般稱為 Steepest Descent direction。 由於比較簡單, 通常也做為一開始嘗試

的選擇。 不過當函數的本身或最小值附近呈現較平滑的趨勢時, 這個方式將出現

收斂緩慢的情況。

6.2 練習

在進行以迭代法計算多變量函數最小值之前, 如果能將函數圖形畫出來, 將有助於

Page 64: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

64 MATLAB 的數學實驗

起始值的選擇, 選取適當的迭代方向。 以下將先練習三維函數圖形的繪製。

範例1: 繪製下列函數的圖形

f(x1, x2) =1

2πe−

x21+x2

22

繪製立體函數圖形的觀念如平面圖的作法:

1. 首先必須先訂出X − Y 平面的範圍與格子 (grids), 其 MATLAB 指令如

[X,Y]=meshgrid(變數 X 的範圍, 變數 Y 的範圍)

矩陣 X 與 Y 代表 X-Y 平面上格子點上的 X 與 Y 座標。 關於 meshgrid

的詳細用法請自行 help meshgrid。 圖6.2是執行 [X,Y]=meshgrid(-2:2,-

1:3) 的結果。 如果 X 與 Y 的座標範圍一樣, 指令中只需輸入一組範圍即

可。

2. 利用 X 與 Y 計算函數在平面上每一個格子點上的函數值 Z。 在 help

meshgrid 裡面可以看到相關的用法。 圖6.3展示以 meshgrid 的概念繪

製函數 z = f(x, y) = xe−x2−y2的立體圖。 圖中可以清楚的看出 X-Y 平

面的格子點狀及其對應的 Z 值高度。

3. 繪製函數圖。 立體函數圖的指令很多, 如 mesh, surf, contour 等。

4. 利用 Matlab 的圖形旋轉功能 (在圖形工具列選擇 「Rotate 3D」), 以滑鼠

適度的旋轉圖形的角度, 找出一個容易觀察極值的位置, 並藉此調整繪圖的

範圍。

函數圖如圖6.4所示。 圖6.4(b) 的等高線圖特別加了一條顏色帶 (colorbar), 表

示高度或大小, 在圖形的工作列上可以找到這個功能, 或是在 contour 指令後面

加上 colorbar 的指令。 另外, 等高線圖是個平面圖, 有時會因為 XY 軸的不均衡,

Page 65: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

6. 多變量函數之最小值 65

圖 6.2: meshgrid 的概念

造成視覺上的落差, 譬如, 應該看起來是正圓形的圖, 卻變成橢圓。 以本範例的函

數為例, 這是個 XY 軸 (x1 vs. x2) 對稱的圖形, 為彰顯此對稱性, 可以在圖形

產生後加上以下的指令

axis square

製作立體圖也可以採匿名函數的方式, 如

f = @(x, y)exp(−(x.∧2 + y.∧2)/2)/(2 ∗ pi);

x=-3:0.1:3;

y=-4:0.1:4;

Z=zeros(length(y),length(x));

for i=1:length(x)

for j=1:length(y)

Z(j,i)=f(x(i),y(j));

end

end

mesh(x,y,Z)

xlabel(’X’),ylabel(’Y’)

範例2: 繪製下列函數的圖形

f(x1, x2) = (x1 − 2)4 + (x1 − 2)2x22 + (x2 + 1)2 (6.6)

Page 66: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

66 MATLAB 的數學實驗

圖 6.3: meshgrid 的概念與立體圖

圖形如圖6.1所示。 習者可以自行翻轉圖形找到最佳觀察的角度, 也可以多利用其

他繪製立體圖的指令 (譬如,contour), 看看是否有更理想的視覺效果。

範例3: 推導函數(6.6)的梯度向量5f(x)及Hessian Matrix 52f(x)

以演算法計算極值, 通常需要紙筆推導到一定的程度, 才進行程式的寫作, 不是忙

亂的一陣砍殺或是坐在哪兒發呆不知從何下手。 因此在真正應用演算法之前, 計

算梯度向量及 Hessian Matrix 是必要的。

範例4: 寫程式計算函數(6.6)的最小值。

運用演算法前, 最好先將演算法的步驟寫下來 (作業1), 再進行程式的寫作, 能力

未敷之際, 切忌憑空築樓, 否則程式錯了不容易除錯。 另外計算目標函數值時, 可

以使用匿名函數的方式, 讓整個程式看起來更簡潔。 由於 Newton-Raphson牽涉

Page 67: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

6. 多變量函數之最小值 67

(a) (b)

圖 6.4: (a) 函數的立體圖 (mesh)(b) 等高線圖 (contour)

到 Hessian Matrix 的二次導數, 有時候推導起來非常繁複。 因此, 簡單的 steep-

est descent 法通常是演算法的首選。 不過我們還是可以利用這個簡單的函數, 來

看看兩者的收斂情況。

MATLAB當然也提供計算多變量函數最小值的指令,fminsearch, 配合其第三個

參數 OPTIONS 的設定, 同樣可以觀察到函數往區域極值收斂的過程, 以下程式

片段可以參考

f = @(x)(x(1)− 2).∧4 + (x(1)− 2).∧2. ∗ x(2).∧2 + (x(2) + 1).∧2;

fminsearch(f, [0 0], optimset(′DISPLAY ′,′ iter′))

其中第二個參數代表起始值, 第三個參數使用 optimset 指令指定最佳化的過程

中欲顯示的細節。

6.3 觀察

1. 不論是式 (6.3) 的 Steepest Descent 或式 (6.5) 的 Newton-Raphson 的

移動方向, 都不能保證可以帶領函數值往下探底, 因此所謂的 「步伐調整」

xk+1 = xk + βdk

仍是必須的。請參考前章 「演算法: 計算函數的極值」關於 「步伐調整器」β的

選擇。

Page 68: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

68 MATLAB 的數學實驗

2. 關於 Newton-Raphson method 的合理性、 限制, 請參考[1], 或從作業2

中略探一二。

3. 仔細觀察不同的dk(式 (6.3) 與式 (6.5)) 在程式進行過程的收斂速度。 甚

至可以記錄過程中的函數值 , 再繪製函數值隨著方向迭代的次數逐漸下降

的趨勢。 參考文獻[1]提供兩者收斂速度的理論分析。

6.4 作業

1. 請寫出適當的演算法, 用以計算函數的最小值。

2. Newton-Raphson method 的方向選擇, 如式(6.3), 可由函數的泰勒展開

式得到驗證。 多變量函數f(xk+1)的泰勒展開式寫為

f(xk+1) = f(xk+dk) = f(xk)+5f(x)Tdk+1

2dT

k52f(x)dk+O(||dk||3)

假設||dk||夠小, 可以省略O(||dk||3), 證明式 (6.3)的 Newton-Raphson

direction 為下列最小值問題的解

mindk

f(xk+1)

3. 著名的 Rosenbrock’s Banana 測試函數

f(x, y) = 100(y − x2)2 + (1− x)2

常被用來測試極值演算法, 請試著繪製其立體圖 (mesh) 與空照圖 (con-

tour), 再利用本單元介紹的兩個方法計算最小值, 並比較其收斂的情況。

4. 自行找一個兩個變數的函數, 繪製函數圖 (mesh 與 contour) 並計算最小

值。

5. 比較不同的迭代方向式 (6.3) 與式 (6.5) 的收斂速度, 譬如到達同一個函

數值所花的時間。 此時可以觀察幾個不同函數值, 由大到小, 分別記錄兩種

不同方式所花的時間, 最後畫出一張圖比較兩者收斂的情況; 橫軸代表 「函

數值」 由大到小, 縱軸代表時間。 注意: 除dk不同外, 其他條件必須相同, 譬

如起始點。

Page 69: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

參考文獻

[1] J.E. Dennis, R.B. Schnabel, ”Numerical Methods for Unconstrained

Optimization,” Prentice Hall.

69

Page 70: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

70 MATLAB 的數學實驗

Page 71: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

第 7 章

群組分類: 線性迴歸與最小平方法

本單元討論 「Supervised Learning」 中屬於類別 (即輸出變數 Y 是類別型的資

料) 資料的群組分辨, 並且著重在最簡單的 「兩群組 (two classes)」 資料判別。 透

過幾個簡單、 典型的方法, 實際去做群組的鑑別。 過程中對 Matlab 程式設計的

技巧、 資料的產生及圖形的繪製都有進一步的延伸, 也是本課程真正的目的。

本章將學到關於程式設計

群組資料的繪製技巧、 排序資料的索引技巧及最小平方法的矩陣計算方式。

〈本章關於 MATLAB 的指令與語法〉指令:sort, set, mvnrnd

71

Page 72: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

72 MATLAB 的數學實驗

7.1 背景介紹

許多應用科學牽涉到從資料 (data) 中分析出所需要 (含) 的資訊 (information)。

希望從已知的資料中瞭解問題的本質, 進而能控制或做出預測。 這些資料通常有

兩種型態; 其一, 包含特性 (features) 資料及結果 (outcome) 資料, 從收集或

量測問題的特性 (或特徵) 資料及相對的結果資料分析出兩者的關係, 並進一步

計算相關的參數, 最後確立模型。 當給予新的特徵資料時, 便可以根據這個確立的

模型產生結果做為預測。 由於有結果資料做為模型建立的根據, 這些問題歸類為

「Supervised Learning」。 譬如圖7.1的示意圖, 未知模型的輸入變數X1.X2 代

表特徵值, 輸出變數 Y 代表對應的組別。

圖 7.1: supervised Learning

其二, 只有特徵資料, 不知其群組屬性。 由於沒有明確的輸出結果做為對照, 這類

問題相對的困難, 稱為 「Unsupervised Learning」, 通常要先從特徵資料裡去找

出隱藏的群組關係, 一般也稱為 「Clustering」。

本單元討論 「Supervised Learning」 中屬於類別1 (即輸出變數 Y 是類別型的

資料) 資料的群組分辨, 並且著重在最簡單的 「兩群組 (two classes)」 資料判別。

透過幾個簡單、 典型的方法, 實際去做群組的鑑別。 過程中對 Matlab 程式設計

的技巧、 資料的產生及圖形的繪製都有進一步的延伸, 也是本課程真正的目的。

1輸出資料概分兩種:quantitative 及 qualitative, 歸類問題的屬性時常以此為分別。 當輸出

是 quantitative 型的資料, 屬於迴歸分析 (regression) 的範疇, 當輸出是 qualitative, 叫做分

類 (classification) 或分群。 輸入資料當然也有不同的類型, 不過應用的方法上差別比較小。 Re-gression與 classification 在方法上也有許多類似之處, 因為在 qualitative 資料的表達上, 通常會以數字來代表, 譬如 1 代表 「成功,」 0 代表 「失敗。」 這樣一來兩者的差距變模糊了, regres-sion的方法也可以用在 qualitative 的資料上。

Page 73: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

7. 群組分類: 線性迴歸與最小平方法 73

為求簡單起見, 假設輸入資料具兩個維度, 即具X1, X2 的兩個特徵值, 且每一筆

已知資料的群組別也是已知。 譬如圖7.2顯示200筆已知資料, 包含輸入 (X1, X2)

與輸出 (不同的圖示及顏色代表不同的組別), 其關係亦如圖7.1所示。 而面臨的問

題是, 當給予一組未知群組別的資料時, 如何預測其組別?

圖 7.2: 每群各有 100 筆資料的兩個群組

圖7.2的 200 筆資料明顯的將所在平面的空間分成兩半, 左半邊屬於群組 1, 右半

邊屬群組 2。 當一筆新的資料需要判別其群組屬性時, 只要看它落在平面上的哪一

邊, 即可判定。 但問題是, 分割平面空間的界線 (separate line) 如何界定? 這條

線將做為資料群組預測的根據, 但從圖7.3來看, 這條分界線似有無限可能, 不同

的方法形成的分隔線也不同, 將如何判斷其優劣呢?

要在兩群組的資料間劃上一條適當的分界線, 有一些簡單的方法要在這個單元介

紹, 並以理論與實作並進的方式逐步完成程式的設計。 之後的單元接陸續介紹其

他方法做群組的鑑別, 本單元介紹線性迴歸模型與最小平方法在群組分析上的應

用。

Page 74: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

74 MATLAB 的數學實驗

圖 7.3: 兩個群組的可能分界線

假設圖7.1的輸入輸出關係為 「線性迴歸模式,」雖然輸出資料屬於類別資料 (Class

1 及 Class 2), 我們仍可以假設當輸入資料屬於群組 1 (Class 1) 時, 輸出變數

以數字表示, 譬如:Y = 0, 另一個群組則為 Y = 1。 將類別資料量化之後的問題,

便可以直接套入以下的線性迴歸模式 (Linear Regression Model) 來分析,

Y = β0 + β1X1 + β2X2 (7.1)

根據 N 筆已知的輸入輸出資料, 迴歸係數 β0, β1, β2 以最小平方法求得的最佳

解為

β = (XT X)−1XTy (7.2)

其中

Page 75: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

7. 群組分類: 線性迴歸與最小平方法 75

β =

β0

β1

β2

, X =

1 x1(1) x2(1)

1 x1(2) x2(2)...

......

1 x1(N) x2(N)

,y =

y(1)

y(2)...

y(N)

(7.3)

分別代表迴歸模型模型的參數估計、 輸入及輸出資料。 式 (7.2假設 (XT X)−1 存

在, 而每個輸出值 y(k) 根據其類別, 非 0 即 1。

群組判別: 當給予一個新的輸入資料x = (x1, x2), 根據迴歸模型 (7.1), 其輸出

(擬合值) 為:

Y = xT β (7.4)

其中 xT = [1 x1 x2]。 如何從這個輸出值判斷資料得群組屬性呢? 在迴歸模型下

的擬合值不一定剛好是 0 或 1, 它可以是任何數值, 但作為類別判斷時, 可以依下

列規則取代: 假設 G 代表判定的類別:

G =

CLASS1 if Y ≤ 0.5

CLASS2 if Y > 0.5

換句話說, 以Y = xT β = 0.5 做為平面空間中兩個群組的分界線, 將R2平面一分

為二, 線的一邊表示為集合{x|xT β ≤ 0.5}為 CLASS1, 另一邊則為 CLASS2。

很明顯的, 這條分界線的形成受到下列因素的影響:

• 已知資料X與y

• 迴歸模式 (7.1)

• 最小平方法 (β的估計)

以下練習協助初學者如何計算β值與畫出群組分佈圖及分界線。

Page 76: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

76 MATLAB 的數學實驗

7.2 練習

舉兩組資料為例 (從網頁下載 la 1.txt, mix.mat), 如圖7.4所示。

(a) (b)

圖 7.4: 群組資料

在計算出分界線之前, 通常會先將資料畫出來觀察其群組關係。 當然這僅限於兩

個輸入變數以下的情況。 左邊的資料 (la 1.txt) 是模擬出來的, 右邊 (mix.mat)

則來自參考文獻 [1]的提供的資料。 以下練習可以協助畫出上面的圖。

範例1: 根據輸出資料 Y 的類別, 在 X1-X2 平面上以不同顏色或符號描繪出群

組的 「樣子,」 如上面看到的兩張圖。

在實際的應用上, 資料的來源常不是自己可以控制的, 因此必要的時候必須做調

整, 才能讓寫好的程式順利執行。 這裡特別設計不同的資料 la 1.txt、mix.mat 對

輸出類別資料的安排不一樣, 程式的寫作也因之有所不同。 mix.mat的資料已經

按類別排序好, 內含兩個變數資料共200筆資料, 分別是輸入的特徵資料 x 與輸

出的群組資料 y, 其中 y 前 100 筆值為 0 代表群組 1, 後 100 筆值為 1 代表群

組 2。 下列指令畫出圖7.4(b)

Page 77: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

7. 群組分類: 線性迴歸與最小平方法 77

load mix

x1=x(:,1);

x2=x(:,2);

plot(x1(1:100),x2(1:100),’*’)

hold on

plot(x1(101:200),x2(101:200),’or’)

hold off

第2個 plot 指令的第三個參數 ’or’代表以紅色 (r) 英文字母’o’為符號描點。

另外, 圖7.4(a) 呈現模擬資料 la 1.txt 的散佈圖。資料 la 1.txt 是一個 200×4的

矩陣, 前兩行代表兩個輸入的特徵值, 後兩行代表輸出的群組值。 由於 la 1.txt 資

料不按輸出類別資料排序, 作圖時上可以

1. 先根據類別排序 (指令:[Y,I]=sort(y)), 記得輸入資料 x1,x2 也必須跟著

排序, 譬如

D =load(’la 1.txt’);

[ Y,I ]=sort(D(:,3)); %按第3行排序, 由小到大

D=D(I,:); %根據排序的索引值 I, 重新排列原資料矩陣

x1=D(:,1); %排列後的輸入資料

x2=D(:,2);

plot(x1(1:100),x2(1:100),’*’)

hold on

plot(x1(101:200),x2(101:200),’or’)

hold off

2. 完全不排序, 根據輸入的群組別, 直接寫一個迴圈將每一筆資料畫上去。

繪製如圖7.4的散佈圖, 方式很多, 主要是藉由不同的符號或顏色來區分群組。 若

要呈現如 (a) 圖有顏色的數字, 可以利用 text 指令取代 plot

Page 78: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

78 MATLAB 的數學實驗

axis([min(x1)-1 max(x1)+1 min(x2)-1 max(x2)-1])

H=text(x1(1:100),x2(1:100),’1’);

set(H,’color’,’blue’)

H=text(x1(101:200),x2(101:200),’2’);

set(H,’color’,’red’)

指令 text 適用在圖形上做標記或文字說明, 不能單獨使用, 因此第一行的 axis

指令用來產生空白圖形, 方便 text 的使用。 指令 axis 的四個參數分別設定 X 軸

與 Y 軸的範圍。 有了空白圖形, text 根據前兩個參數(x1, x2)代表的平面的座標

位置, 印出第三個參數的文字, 譬如’1’。 當 x1,x2 是 1×N 或 N × 1 的向量變

數時, 可以同時在 N 個座標位置根據第三個參數印上相同或不同的文字。 指令中

的 H 代表圖形上的 「物件」(Object Handle), 利用 set 指令可以改變其外觀, 更

多的外觀選項可以參考該指令的說明。

範例2: 根據範例 1 的資料, 計算迴歸模型的參數 (7.2) 並畫出式 (7.4) 中, Y =

0.5的迴歸線, 也就是兩群組間的分界線。

計算式 (7.2) 的 β 比較簡單, 先從原始資料建構資料矩陣 X 與 y, 再套入反矩

陣的指令 inv 即可。

要畫出兩群組間的分界線Y = 0.5, 需要琢磨一下。 這條分界線的方程式可以表示

β0 + β1x1 + β2x2 = 0.5

為繪圖方便, 可以轉換為

x2 =0.5− β0

β2

− β1

β2

x1

圖7.5展示這兩組資料的迴歸分界線。

Page 79: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

7. 群組分類: 線性迴歸與最小平方法 79

(a) (b)

圖 7.5: 群組分界線

7.3 觀察

1. 當分界線劃上去之後, 有多少資料被錯置組別呢? 錯置的資料愈多, 代表什

麼意義? 當兩個群組部分交錯時, 資料的錯置是否不可避免? 有更好的分

界線可以讓錯置的情況降低嗎?

2. 使用已知的資料做出一條分界線, 企圖將原母體在空間中的範圍切割出來。

這個切割的好壞當然取決於已知資料的品質及分界線的決定方式。 試試看

給予一些新的資料 (從原母體去產生), 測試一下這條分割線能否對新的資

料做出正確的組別判斷? 譬如100個新資料有多少比率被正確辨別?

3. 由於資料的取得誤差或樣本數不夠, 群組的區隔有時候不是很明顯, 當然也

可能是群組本身就非常靠近。 圖7.5(a)的資料看起來分離的很好, 直覺上比

較容易作區域的切割, 如中間的那一條分界線。而圖7.5(b)的兩個群組相對

緊密, 即使能劃上一條分隔線, 也可能必須選擇曲線比較能滿足現有資料能

提供的訊息。 不過根據有限的資料做出最好的判斷, 不就是這門學問的精神

所在嗎。

4. 當群組數量大於2時, 分界線將如何切割? 想一想。 手癢的話就動手做看看

吧!

5. 本單元的資料模擬自 Bivariate Normal Data, 而且從 Σ 的假設, 兩個

變數還是獨立的。 如果變數間有相依性, 本單元的方法還是可行嗎? 如何

Page 80: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

80 MATLAB 的數學實驗

去模擬具相依性的資料呢? 參考 MATLAB 關於多變量常態亂數產生器

mvnrnd 的使用方式。

7.4 作業

1. 證明式 (7.2) 是迴歸模型 (7.1) 的最小平方法解, 即

β.= min

β||Xβ − y||2

2. 畫出範例 2 的分界線。

3. 資料 la 1.txt 提供兩組輸出值 y1 及 y2 即第3,4行。 這兩組輸出值恰為互

補值。 可以將 y1 作 CLASS1的值,y2 當作 CLASS2的值。 利用 y2做一

條分界線, 看看和前面利用 y1 做出來的分界現有何不同?

4. 同上, 可不可以兩組資料同時利用, 即將式 (7.2) 中的 y 換成 [y1 y2]。 妳

不需要完成這件工作, 只需想想看, 用紙筆推敲一下即可。

Page 81: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

參考文獻

[1] T. Hastie, R. Tibshirani, J. Friedman, ”The Elements of Statistical

Learning:Data Mining, Inference, and Prediction,” Springer.

[2] A.G. Rencher, ”Multivariate Statistical Inference and Applications,”

John Wiely & Sons, INC.

81

Page 82: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

82 MATLAB 的數學實驗

Page 83: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

第 8 章

群組分類: Nearest Neighbor Method

對空間中的群組資料作分組切割, 在應用上很常見, 因此衍生的方法也很多。 上

一個單元採用線性迴歸的模式, 並運用最小平方法確立模型的參數。 這個方式雖

簡單, 但是切割的效果往往隨著資料來源的佈散愈趨緊密而顯得 「心有餘而力不

殆。」 這個單元將面對相同的問題提出另一個簡單的方式, 看看從不同的思維模式

是否能得到比較令人滿意的結果。

從二度空間的資料來看, 上個單元線性迴歸模式試圖在交錯的資料群中畫出一條

分界線, 將空間一分為二, 進而確立群組在空間中的的範圍。 這條線切的好不好,

影響了後續做群組判別的準確性。 這個單元從 「可能性、」「機率論」 觀點作為切入

點, 多了些假設, 卻要看看效果如何。

本章將學到關於程式設計

群組資料的繪製技巧、 各種等高線圖(contour plot) 的繪製、 排序資料的索引技

巧及亂數資料的產生技巧。

〈本章關於 MATLAB 的指令與語法〉指令:sort, find, contour

83

Page 84: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

84 MATLAB 的數學實驗

8.1 背景介紹:Nearest-Neighbor Method

有時候我們對資料的 (或可能的) 來源並非一無所知, 但是迴歸模式採用的最小平

方法, 並沒有充分利用資料本身的訊息。 從資料的變異性, 我們希望資料的來源或

資料的本身可以提供足夠的訊息, 做為新資料群組判別的依據。 這樣的需求把這

個問題帶進 「機率」 的範疇來解決。 假設 Y 及 f(X) 代表輸出變數與輸出預測

值, 1 其中 X ∈ Rp 表示 p 個輸入變數。 我們期望輸出值與預測值的誤差愈小愈

好, 如果輸入變數 X 與輸出變數 Y 的聯合機率密度函數 Pr(X,Y ) 已知的話,

這個問題可以寫成:

minf(X)

EXY

[(Y − f(X))2

](8.1)

也就是找一個輸入與輸出變數間的關係式 f(·) , 使得輸出值 Y與其預測值 f(X)

平方差的期望值越小越好。 有別於不論機率特性的 「最小平方法 (least squares)」,

這個方法的名稱也有個”squares”叫做 「Minimum Mean Squares」。 在已知樣

本值 X = x 的條件下, 經過一番推導之後(作業1), 它的最佳解如下:

y = f(x) = EY |X (Y |X = x) (8.2)

其中 X,Y 代表輸入輸出變數,x, y 表示輸入值及輸出的預測值。 式 (8.2) 說明

當輸入值為 x 時, 最佳的輸出預測值為輸出變數的 「條件式均值(conditional

mean)」。

接下來的問題是如何計算 y = EY |X (Y |X = x)? 期望值的表示法是理論上的

東西, 要如何落實到實際的應用呢? 假設不知道機率密度函數 Pr(Y |X), 如何得

到這個期望值呢?

一般我們會使用平均數來估計這個期望值。 譬如下面是個不錯的估計式

1函數 f(·)代表輸入與輸出間的關係, 譬如上個單元的迴歸模式 f(X) = β0+β1X1+β2X2。

Page 85: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

8. 群組分類: Nearest Neighbor Method 85

y = Ave(yi|X = x) (8.3)

其中 Ave(·) 代表求平均值。

這個估計式還是面臨實際的困難:

• 當X = x 是從已知的輸入資料中取得, 通常筆數不多, 多半都只有一筆資

料, 其輸出的樣本平均數估計並無意義。2

• 當X = x是需要預測輸出值的新資料時, 更沒有計算輸出樣本平均數的可

能。

下面這個輸出預測值定義舒緩了這些困擾

y = Ave (yi|xi ∈ Nk(x)) =1

k

∑xi∈Nk(x)

yi (8.4)

從已知的資料中找到 k 個最靠近 x 的資料(這是 Nk(x) 的意義), 將這些鄰近資

料的 y 值平均起來作為 「條件式均值」 的估計, 這個方法叫做 Nearest-Neighbor

method。

目前為止所提到的輸出變數並不侷限任何型態, 但若輸出變數為群組屬性的類別

資料時, 如式 (8.1) 的 「Minimum Mean Squares」 問題可以寫成,

ming(X)

EXG [L(G, g(X))] (8.5)

由於是類別資料的關係, 其輸出群組 G 與預測群組 g(X) 的誤差以 「Loss func-

tion」 L(G, g(X)) 取代原先的平方差。 當 L(G, g(X)) 定義為

L(G, g(X)) =

0 if G = g(X)

1 if G 6= g(X)

2當然也可以嘗試自 P (Y = X = x) 中抽取適量的樣本並計算其均值。

Page 86: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

86 MATLAB 的數學實驗

式 (8.5) 的最佳解為

g(X) = gk if Pr(gk|X = x) = maxg∈G

Pr(g|X = x) (8.6)

其中 gk 代表第 k 個群組 (group),G 是所有群組的集合。 這個結果說明: 當輸入

值為 x 時, 其所屬群組的Minimum Mean Squares 預測為

「在所有的群組中, 群組機率密度函數在 x 處的值最大者」

這也稱為 Bayes classifier。3 式子(8.2)(8.6) 的推導將在課堂上說明, 或是參

考[1]。 不管哪一種輸出的型態, 這裡都使用到 「後驗機率」(posterior probabil-

ity) 的觀念, 也就是當給定輸入變數 X = x, Y(G) 值的可能性(機率)。 Bayes

之名也來自於此。

群組判別: 從式(8.6) 中似乎看不出一個明顯的 「分界線」 方程式, 無法像前一個

單元那樣根據方程式畫出一條分界線, 更何況機率密度函數Pr(G|X = x)也是

未知。 不過如同前一個單元將迴歸模式應用在類別資料上, 當假設兩個群組的輸

出為 0 (群組1) 與 1 (群組2) 時, 式 (8.4) 可以當作式 (8.6) 的估計式, 並配合

下列的群組判別式,

x ∈

g1 if y ≤ 0.5

g2 if y > 0.5(8.7)

式 (8.4) 的 y ≤ 0.5 相當於 式 (8.6) 的 Pr(g1|X = x) > Pr(g2|X = x)。 這

個方法的表現到底如何? 比起前面的線性迴歸模式好或壞? 有什麼缺點? 有什麼

限制? 只要把程式寫出來, 拿幾組資料實際來測試一番便知分曉。

8.2 練習

範例1: 舉資料mix.mat 為例 (從網頁下載的, 資料來源 [1]), 按前一個單元的繪

3這個結果看起來似乎是 「廢話,」 因為當機率密度函數 Pr(g|X) 未知時, 如何知道當 X = x時的群組機率密度函數值呢? 不過這卻是很重要的理論, 它說明在期望預測值與實際值的誤差最

小的前提下, 最好的預測值是來自在X = x處有最大機率密度函數值的群組。

Page 87: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

8. 群組分類: Nearest Neighbor Method 87

圖方式, 畫出如圖8.1(a)所示的群組資料。 圖 (b) 便是利用 Nearest-Neighbor

method 切割空間的結果。 試著按下列的說明複製圖8.1(b)。

(a) (b)

圖 8.1: 群組資料與空間分割

由於 Nearest-Neighbor method 並沒有定義出一個分界線的方程式, 無法畫出

這條線, 不過可以如圖8.1(b) 的作法, 在一定的空間範圍內, 將空間等份成格子狀

(grid), 每個格子的座標代表一個資料值 x, 將每一筆資料當作新資料一樣的拿出

來判斷其類別(大部分的格子點都不在已知的資料裡), 依式(8.4) 與 (8.7), 為每

個位置劃上不同的符號做為群組的區別。 格子狀的粗細與組別符號決定了畫出來

的感覺, 不妨試試看不同的格子密度與群組符號或顏色。

式 (8.4) 的估計式中需要找出 「靠近 x 的 k 個已知資料」, 這個 「靠近」 的測量方

式可以採用 Euclidean Distance。 假設 x1,x2, · · · ,xN為 N 個已知資料, x為

空間中某個待判別群組的資料, 程式中需要計算 x 與所有已知資料的距離, 再從

中選取最靠近的 k 筆資料, 最後再將這 k 筆資料的群組值 (0或1) 平均起來, 即

為式 (8.7) 中的 y值, 程式片段如下

Page 88: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

88 MATLAB 的數學實驗

% 參數準備

interval=0.1;%格子點距

k=15; % k nearest points

xmin=-3; xmax= 5;ymin=-2;ymax= 3; % X 與 Y 的範圍

gx=xmin:interval:xmax;%格子 X 座標

gy=ymin:interval:ymax;%格子 Y 座標

B=zeros(length(gx),length(gy));%存放相鄰 k 個點的 y 值平均

for i=1:length(gx)%計算距離並取前 k 個 y 值的平均

for j=1:length(gy)

d=(x1-gx(i)).∧2 + (x2-gy(j)).∧2;%計算每個格子點與所有樣本的距離

[dd,I]=sort(d);% 排序

B(i,j)=mean(y(I(1:k)));%取出最相鄰 k 個點的 y 值平均

if B(i,j) >0.5%決定群組並描繪其群組符號

plot(gx(i),gy(j),’-r’)

else

plot(gx(i),gy(j),’-g’)

end

end

end

程式中的x1, x2 與 y 變數分別代表樣本資料與其群組別。

範例2: 運用繪圖的技巧為圖8.1(b) 的兩個顏色的邊界劃上線條, 如圖8.2。

雖然 Nearest-Neighbor method 並未定義出分界線方程式, 不過運用繪圖的技

巧, 仍可以巧妙的描繪出這條線。 其作法是先將前一個範例所提到的每一個格子

點所計算出來的 Y 值平均依式 (8.7) 轉換成組別資料 (0或1), 如以下程式片段

%呈上述程式

I=find(B > 0.5);

B(I)=1; % group 2

I=find(B < 0.5);

B(I)=0; % group 1

Page 89: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

8. 群組分類: Nearest Neighbor Method 89

圖 8.2: 分界線的繪圖技巧

根據這些組別資料 (B 值) 與其座標值 (X-Y 值) 繪製 contour 的等高線圖, 或

但只畫0.5這條線。 程式片段如下

%呈上述程式

[X,Y]=meshgrid(xmin:interval:xmax,ymin:interval:ymax);

contour(X,Y,B’,0.5) %注意矩陣 B 的轉置以配合 XY 矩陣

請先瞭解在 Matlab 裡面 contour 的用法, 它同時也是繪製不規則函數圖型的利

器。 下列指令可供參考

contour(X,Y,Z) %多條等高線圖

contour(X,Y,Z,0.5) %繪製 1 條 Z 值為0.5的等高線

contour(X,Y,Z,[0 1]) %繪製 2 條 Z 值為0,1的等高線

範例3:Nearest Neighbor method 對空間的切割並不一定是連續的, 試試看不

同的 k 值 (譬如 k = 15, 14, · · · , 1), 觀察空間被切割的情況。

Page 90: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

90 MATLAB 的數學實驗

當 k = 1 時, 可說是依據已知資料對空間的切割到了極致, 如圖8.3所示。 與前一

個單元的迴歸直線對照, 恰似兩個極端。 其他的分割方式都介於這兩者之間。

圖 8.3: k=1的空間分割圖

圖8.3的繪圖方式相當具有視覺效果, 可以兩種方式達到, 其一

contour(X,Y,Z,’Fill’,’on’)

或是以繪圖編輯器 (Property Editor) 來注入顏色。

8.3 觀察

1. Nearest-Neighbor method 做出來空間切割並非直線, 往往都是不規則形

狀。 換句話說, 分界線應該是很複雜的非連續函數。

2. k 值的選擇對於空間的切割有重大的影響, 對新資料作分類預測時當然也

會不同。 試著嘗試不同的 k 值, 看看切割出來的空間有何不同?

Page 91: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

8. 群組分類: Nearest Neighbor Method 91

3. 採用 Nearest-Neighbor method 並不是在找一條空間的分界線, 相反的

它是比較區域型 (範圍較小) 的, 在一個小區域的空間中找界線, 這個區域

的大小由 k 及資料的分佈情形來決定。

4. 如果將估計值 (8.4) 改為 y = Median (yi|xi ∈ Nk(x)), 結果會變好還

是變壞? 做做看。

5. 式 (8.4) 的估計值將鄰近點視為等值影響, 對某些區域來說並不 「公平」,

如果依距離之遠近改變其權重, 是否能提供更平滑的分界線? 請試試看依

常態分配的機率值來權衡其重要性。

8.4 作業

1. 推導出式 (8.2), 其中

EXY (Y − f(X))2 =∫ ∫

(Y − f(X))2Pr(X,Y )dXdY

=∫ ∫

(Y − f(X))2Pr(Y |X)Pr(X)dXdY

= EXEY |X((Y − f(X))2|X)

2. 推導出式 (8.6), 其中

EXG [L(G, g(X))] = EX

K∑k=1

L(gk, g(X))Pr(gk|X)

3. 以 mix.mat 資料為例, 利用本單元的方法, 依 k=15,10,5,1 各畫出分界線

(共四張圖)。

4. 任選一個 k 值, 按 「觀察 (4)」 的建議採 median 取代 average, 畫一張以

顏色及符號分組的圖, 另一張只畫分界線。

5. 不同的 k 值其分割組別的能力不同。 要判斷分割的精準度, 可以將所有的

擬合值與原始值做比較, 看看整體的誤差 (譬如所有誤差值的平方合) 就可

以看出精準度。 請根據 k 值的不同, 從 k=15,10,5,1 分別計算其誤差平方

合, 並畫一張圖來表示其趨勢。

Page 92: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

92 MATLAB 的數學實驗

6. (optional) 從上題的精準度問題來看, 實際上精準度愈高並不代表其分辨

新資料的能力愈好, 針對不同的資料, 會有一個最佳的 k 值, 其對新資料

的分辨能力最好。 請自行產生一組資料 (俗稱 training data) 來決定分界

線, 再產生另一組資料作為測驗這個分界線的測試資料 (test data), 一樣

採誤差平方合來作為優劣的依據。 畫一張圖含兩條線,一條是根據 training

data 所產生的誤差, 另一條是根據 testing data 產生的。 橫軸都是 k 值

(譬如 k= 15, 14, · · · , 1)。 請注意, 這裡的資料可以依下一題的方式產生。

7. k- Nearest-Neighbor classifier(式 (8.4)(8.7)) 其實是 Bayes classi-

fier(式 (8.6)) 的近似版, 當條件式機率分配 P (X|G) 已知時,Bayes op-

timal boundary 可以被準確的計算出來, 如圖8.4所示。

圖 8.4: Bayes optimal boundary

計算 Bayes optimal boundary 的前提是隨機資料的產生機率密度函數

(generating density) 必須已知。 圖8.1(b)的資料 (mix) 來自兩組混合常

態 (Normal Mixtures) 的母體, 每組各由 10 個 bivariate 常態母體組成,

Page 93: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

8. 群組分類: Nearest Neighbor Method 93

第一組 : P (X|G = 1) =10∑

k=1

αkφ(X, µ1k, Σk)

第二組 : P (X|G = 2) =10∑

k=1

αkφ(X, µ2k, Σk)

其中, 混合比例 αk 皆為 110

, 共變異矩陣 Σk 皆為 I/5, 第一組常態分

配的 mean 由一個 bivariate 常態 N((1, 0), I) 產生 10 個, 另一組由

N((0, 1), I) 產生 10 個。 參考資料 mix 亦包含這些 mean.mat 的樣本

(變數名稱 x mean)。 Bayes optimal boundary 為

Pr(G = g1|X) = Pr(G = g2|X) (8.8)

利用貝氏定理並將上述的假設代入 (8.8), 可以得到這條線的數學式子, 用

MATLAB 畫等高線圖, 即為圖8.4所示。 從式 (8.8) 的角度來看,Nearest-

Neighbor method 對兩個群組的分割可說是接近完美的演出。試著將這條

理論上最好的分界線畫出來。

Page 94: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

94 MATLAB 的數學實驗

Page 95: MATLAB íbçıð - web.ntpu.edu.twweb.ntpu.edu.tw/~ccw/statmath/MATLAB_main_1.pdf · 10 MATLAB íbçıð 1.1 *3 MATLABJ•ı¶Vœ˙ FJœø&˙$7k, .âlßÞ…˜,œ@í(x,y) ı ˝(ł¥

參考文獻

[1] T. Hastie, R. Tibshirani, J. Friedman, ”The Elements of Statistical

Learning:Data Mining, Inference, and Prediction,” Springer.

95