Hello大家好,今年數學模組化國賽将于9月中旬舉行,是時候提前做一些準備了。
本次模型非常簡單,隻是介紹比較得詳細,我下次注意,争取限制下字數。
文末準備了 層次分析-python 模型的實作,簡單懂得模型原理便能一眼看懂代碼。
文章目錄
一、層次分析法的例題
1.1 兩兩比較獲得判斷矩陣
1.2 一緻性正互反矩陣的引入
1.2.1 一緻性檢驗的步驟
1.3 根據一緻性正互反矩陣計算權重
二、層次分析法
步驟:
三、層次分析法的一些局限性
四、模型拓展
1. 多個準則層:
2. 準則不對應全部方案:
*3. 一個準則隻對應自己的方案
五、代碼展示
代碼1:
代碼2:
層次分析(The analytic hierarchy process) 簡稱AHP,是模組化比賽中最基礎的模型之一,其主要用于解決評價類問題(例如:選擇哪種方案最好、哪位運動員或者員工表現的更優秀等。)
該方法仍具有較強的主觀性,判斷/比較矩陣的構造在一定程度上是憑感覺決定的,一緻性檢驗隻是檢驗 感覺 有沒有自相沖突得太離譜。
引例:
聯考結束,坤坤面臨選擇大學的問題,擺在他面前的選擇有兩個:大學A和大學B。
坤坤覺得,他最關心的有四個方面:學習氛圍,就業前景,男女比例,校園景色,權重分别為0.4,0.3,0.2,0.1。
那麼坤坤要完成的,就是通過調查這兩所學校的上面4個特征名額,對其進行打分,完成下表:
權重 | 大學A | 大學B |
學習氛圍 | 0.4 | |
就業前景 | 0.3 | |
男女比例 | 0.2 | |
校園景色 | 0.1 |
最終,經過坤坤百度以及各種調查,打分如下(要求同一特征不同大學分數之和為1):
權重 | 大學A | 大學B | |
學習氛圍 | 0.4 | 0.6 | 0.4 |
就業前景 | 0.3 | 0.5 | 0.5 |
男女比例 | 0.2 | 0.3 | 0.7 |
校園景色 | 0.1 | 0.2 | 0.8 |
經計算:
- A = 0.4*0.6 + 0.3*0.5 + 0.2*0.3 + 0.1*0.2=0.47
- B = 0.53
B>A 是以最終小坤去了大學B。
即打分法解決評價問題時,隻需要我們補充完成下面這張表格即可:
權重 | 方案1 | 方案2 |
名額1 | ||
名額2 | ||
名額3 | ||
名額4 |
同顔色單元格之和為1。
一、層次分析法的例題
題目:
選擇好大學後,坤坤準備在開學前去旅遊,他決定在城市A,城市B,城市C中選擇一個作為目标地點。
請你确定評價名額、形成評價體系來為坤坤同學選擇最佳的方案。
從上面居中的這段話中,很直接得就告訴我們這是一個評價類問題,那麼我們不妨用剛剛學到的層次分析來解決這個問題。
解決評價類問題,大家首先要想到以下三個問題:
- 我們評價的目标是什麼?
- 最佳旅遊目标的選擇
- 我們為了達到這個目标有哪幾種可選的方案?
- 城市A、B、C
- 評價的準則或者說名額是什麼?
- 我們根據什麼東西來評價好壞?
那麼問題來了,對于第三個問題,題目沒給相關資料支撐,比如哪裡的空氣好啊費用低呀... 需要我們查閱相關的資料。
一般而言,前兩個問題的答案很容易得到,第三個問題的答案需要我們根據題目中的背景材料、常識以及網上搜集到的參考資料進行結合,從中篩選出最合适的名額。
這個時候,我們就可以去知網(或者萬方、百度學術、谷歌學術等平台)搜尋相關的文獻,這樣一來,我們的論文也就有文獻引用了,讓我們的資料等看起來有理有據,顯得專業,還能明目張膽地借鑒學習一下他們論文中的觀點。
推薦一個據說很厲害的網站:蟲部落快搜 - 搜尋快人一步
那麼現在,假如我們替坤坤查詢了資料後選擇了以下五個名額:
- 景點景色
- 旅遊花費
- 居住環境
- 飲食情況
- 交通便利程度
接下來,要對坤坤如何提問才能幫他做出合理的決定?
這就要用到我們最開始學的那張表了
權重 | 城市A | 城市B | 城市C |
景色 | |||
花費 | |||
居住 | |||
飲食 | |||
交通 |
但是,如果我們直接問坤坤:權重多少,城市ABC評分多少,會顯得十分片面且不周全(第二天再問他絕對又換了個數,他自己也記不清。)
在确定影響某因素的諸因子在該因素中所占的比重時,遇到的主要困難 是這些比重常常不易定量化。此外,當影響某因素的因子較多時,直接 考慮各因子對該因素有多大程度的影響時,常常會因考慮不周全、顧此 失彼而使決策者提出與他實際認為的重要性程度不相一緻的資料,甚至 有可能提出一組隐含沖突的資料。
——選自司守奎[kuí]老師的《數學模組化算法與應用》
是以,我們采用分而治之的思想,先來處理權重吧~
問題:
- 一次性考慮這五個名額之間的關系,往往考慮不周。
解決方法:
- 兩個兩個名額進行比較,最終根據兩兩比較的結果來推算出權重。
1.1 兩兩比較獲得判斷矩陣
簡單來說就是我們這5個名額分别比較,比如我覺得:景色比花費更重要,飲食比交通非常重要... 通過這樣的方式對不同的重要程度指派 并 最後計算,進而得到權值。
标度 | 含義 |
1 | 表示兩個因素相比,具有同樣重要性 |
3 | 表示兩個因素相比,一個因素比另一個因素稍微重要 |
5 | 表示兩個因素相比,一個因素比另一個因素明顯重要 |
7 | 表示兩個因素相比,一個因素比另一個因素強烈重要 |
9 | 表示兩個因素相比,一個因素比另一個因素極端重要 |
2,4,6,8 | 上述兩相鄰判斷的中值如2是1和3之間 |
倒數 | A和B相比如果标度為3,那麼B和A相比就是1/3 |
接下來,就是兩兩比較五個名額對于選擇最終的旅遊景點的重要性。
我們繪制如下表格,其對角線肯定都為1:
景色 | 花費 | 居住 | 飲食 | 交通 |
景色 | 1 | |||
花費 | 1 | |||
居住 | 1 | |||
飲食 | 1 | |||
交通 | 1 |
問:景色和花費相比的重要程度?
坤:我認為景色比花費略重要,介于同等重要1和稍微重要3之間吧。
問:景色和居住相比的重要程度?
坤: 我認為景色比居住要重要一點,介于稍微重要3和明顯重要5之間吧。
景色 | 花費 | 居住 | 飲食 | 交通 |
景色 | 1 | 2 | 4 | |
花費 | 1/2 | 1 | ||
居住 | 1/4 | 1 | ||
飲食 | 1 | |||
交通 | 1 |
這樣坤坤回答完10次(
),填完了這張用于計算權重的表格(重要性更加穩定精确了):
景色 | 花費 | 居住 | 飲食 | 交通 | |
景色 | 1 | 2 | 4 | 3 | 3 |
花費 | 2 | 1 | 7 | 5 | 5 |
居住 | 1/4 | 1/7 | 1 | 1/2 | 1/3 |
飲食 | 1/3 | 1/5 | 2 | 1 | 1 |
交通 | 1/3 | 1/5 | 3 | 1 | 1 |
注:實際情況下沒有坤坤幫我們回答,層次分析法中這張表是交給‘專家’ 填的,具體我們等後面再說。(其實我們自己憑感覺填,在論文中不說怎麼來的也行,後面會有獲獎案例鑒賞。)
這樣,我們所形成的正互反矩陣,就是層次分析法中的判斷矩陣。
得到判斷矩陣,我們就可以計算出權重了,方法後面再講。
同理,我們可以得到城市A、B、C在景色、花費、居住、飲食、交通所占的權重(得分),是以需要再填5張表格,如問完了坤坤對于城市ABC中景色的看法:
景色 | 城市A | 城市B | 城市C |
城市A | 1 | 2 | 5 |
城市B | 1/2 | 1 | 2 |
城市C | 1/5 | 1/2 | 1 |
其它關于花費、居住、飲食、交通的表我就略了。
注:一個可能出現問題的地方:
坤坤:我覺得x比y好,y比z好,z比x好或一樣好。
如果把語氣加重一些,誰比誰非常好,那麼這種不一緻的現象會更加嚴重。
1.2 一緻性正互反矩陣的引入
此時,我們就要介紹一個東西:一緻矩陣,用它來判斷資料知否合理。
- 若矩陣中每個元素 且滿足 ,則我們稱該矩陣為正互反矩陣。
- 在層次分析法中,我們構造的判斷矩陣均是正互反矩陣。
- 若正互反矩陣滿足 ,則我們稱其為一緻矩陣。
1 | 2 | 4 |
1/2 | 1 | 2 |
1/4 | 1/2 | 1 |
你看,上面這個矩陣就是一緻矩陣。
比如我讓i=1, j=2, k=3, 那麼2*2=4:
令i=2, j=2, k=1, 那麼1*1/2=1/2:
此外除了
一緻矩陣還有個特點,就是行或列對應成比例。
我們引入一緻矩陣,用來檢驗我們構造的判斷矩陣和一緻矩陣是否有太大的差别。
景色(原始) | 城市A | 城市B | 城市C |
城市A | 1 | 2 | 5 |
城市B | 1/2 | 1 | 2 |
城市C | 1/5 | 1/2 | 1 |
景色(一緻矩陣) | 城市A | 城市B | 城市C |
城市A | 1 | 2 | 4 |
城市B | 1/2 | 1 | 2 |
城市C | 1/4 | 1/2 | 1 |
引理:n階正反矩陣A為一緻矩陣時當且僅當最大特征是;
且當正反矩陣A非一緻時,
景色 | 城市A | 城市B | 城市C |
城市A | 1 | 2 | a |
城市B | 1/2 | 1 | 2 |
城市C | 1/a | 1/2 | 1 |
從上圖我們可以發現,當a=4也就是上方剛開始介紹的一緻矩陣,此時最大特征值最小,為3=n也就是矩陣的階數。若a不為4,或a離4越來越遠,不一緻現象越明顯,則其特征值也遞增。
1.2.1 一緻性檢驗的步驟
1. 計算一緻性名額CI
2. 查下表找對應的平均随機一緻性名額RI
n | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
R | 0.52 | 0.89 | 1.12 | 1.26 | 1.36 | 1.41 | 1.46 | 1.49 | 1.52 | 1.54 | 1.56 | 1.58 | 1.59 |
注:在實際運用中,n很少超過10,如果名額的個數大于10,則可考慮建立 二級名額體系,或使用我們以後要學習的模糊綜合評價模型。
3. 計算一緻性比例CR
如果CR < 0.1, 則可認為判斷矩陣的一緻性可以接受;
否則需要對判斷矩陣進行修正。
1.3 根據一緻性正互反矩陣計算權重
以下表為例,雖然不是一緻矩陣,但它的CR<0.1,我們選擇接受不做調整。
(CR>0.1如何調整在後面)。
景色 | 城市A | 城市B | 城市C |
城市A | 1 | 2 | 5 |
城市B | 1/2 | 1 | 2 |
城市C | 1/5 | 1/2 | 1 |
我們取出第一列,做歸一化處理(城市ABC對于城市A的重要性是1、1/2、1/4)。
- 城市A = 1 /(1+0.5+0.2) = 0.5882
- 城市B = 0.5/(1+0.5+0.2) = 0.2941
- 城市C = 0.2/(1+0.5+0.2) = 0.1177
之後我們拿出二三列重複上面操作:
- 城市A = 2 /(2+1+0.5) = 0.5714
- 城市B = 1/(2+1+0.5) = 0.2857
- 城市C = 0.5/(2+1+0.5) = = 0.1429
- 城市A = 5 /(5+2+1) = 0.625
- 城市B = 2/(5+2+1) = 0.25
- 城市C = 1/(5+2+1) = 0.125
這樣我們得到三組權重:
法1:算術平均求權重:
- 第一步:将判斷矩陣按照列歸一化 (每一個元素除以其所在列的和)
- 第二步:将歸一化的各列相加(按行求和)
- 第三步:将相加後得到的向量中每個元素除以n即可得到權重向量
- 城市A = (0.5882+0.5714+0.625)/3=0.5949
- 城市B = (0.2941+0.2857+0.25)/3=0.2766
- 城市C = (0.1177+0.1429+0.125)/3=0.1285
法2:幾何平均法求權重
- 第一步:将A的元素按照行相乘得到一個新的列向量
- 第二步:将新的向量的每個分量開n次方
- 第三步:對該列向量進行歸一化即可得到權重向量
- 城市A = 0.5954
- 城市B = 0.2764
- 城市C = 0.1283
法3:特征值法求權重
假如我們的判斷矩陣一緻性可以接受,那麼我們可以仿照一緻矩陣權重的求法。
一緻矩陣有一個特征值為n,其餘特征值均為0。
- 第一步:求出矩陣A的最大特征值以及其對應的特征向量
- 第二步:對求出的特征向量進行歸一化即可得到我們的權重
景色 | 城市A | 城市B | 城市C |
城市A | 1 | 2 | 5 |
城市B | 1/2 | 1 | 2 |
城市C | 1/5 | 1/2 | 1 |
該表最大特征值為3.0055,一緻性比例CR=0.0053,對應的特征向量:[-0.8902,-0.4132,-0.1918],對其進行歸一化:[0.5954,0.2764,0.1283]
算術平均法 | 幾何平均法 | 特征值法 | |
城市A | 0.5949 | 0.5954 | 0.5954 |
城市B | 0.2766 | 0.2764 | 0.2764 |
城市C | 0.1285 | 0.1283 | 0.1283 |
我們大多數情況下使用特征值法,将其帶入初始要填的表:
權重 | 城市A | 城市B | 城市C |
景色 | 0.5954 | 0.2764 | 0.1283 |
花費 | |||
居住 | |||
飲食 | |||
交通 |
同理這些空着的地方都可以使用同樣的方式。
此時,我們終于得到了這個判斷矩陣:
權重 | 城市A | 城市B | 城市C | |
景色 | 0.2636 | 0.5954 | 0.2764 | 0.1283 |
花費 | 0.4758 | 0.0819 | 0.2363 | 0.6817 |
居住 | 0.0538 | 0.4286 | 0.4286 | 0.1429 |
飲食 | 0.0981 | 0.6337 | 0.1919 | 0.1744 |
交通 | 0.1087 | 0.1667 | 0.1667 | 0.6667 |
城市A最終得分:0.299
城市B最終得分:0.245
城市C最終得分:0.455
是以最後去城市C旅遊。
二、層次分析法
層次分析法(The Analytic Hierarchy Process即 AHP)是由美國運籌學家、 匹茲堡大學教授T . L. Saaty于20世紀70年代創立的一種系統分析與決策的綜合 評價方法,是在充分研究了人類思維過程的基礎上提出來的,它較合理地解 決了定性問題定量化的處理過程。
AHP的主要特點是通過建立遞階層次結構,把人類的判斷轉化到若幹因 素兩兩之間重要度的比較上,進而把難于量化的定性判斷轉化為可操作的重 要度的比較上面。在許多情況下,決策者可以直接使用AHP進行決策,極大 地提高了決策的有效性、可靠性和可行性,但其本質是一種思維方式,它把 複雜問題分解成多個組成因素,又将這些因素按支配關系分别形成遞階層次 結構,通過兩兩比較的方法确定決策方案相對重要度的總排序。整個過程體 現了人類決策思維的基本特征,即分解、判斷、綜合,克服了其他方法回避 決策者主觀判斷的缺點
步驟:
1.分析系統中各因素之間的關系,建立系統的遞階層次結構.
注意:如果你用到了層次分析法,那麼上面這個層次結構圖要放在你的模組化論文中哦。
2. 對于同一層次的各元素關于上一層次中某一準則的重要 性進行兩兩比較,構造兩兩比較矩陣(判斷矩陣)。
看看優秀論文的做法吧:
【2008年國賽B題一等獎】 關于高等教育學費标準的評價及建議
【2016年國賽MATLAB創新獎B題】中國人民大學‐小區開放道路通行影響
準則層—方案層的判斷矩陣的數值要結合實際來填寫,如果題目中有其他資料, 可以考慮利用這些資料進行計算。
例如:有一個名額是交通安全程度,現在要比較開放小區、半開放小區和封閉小區,而且 你收集到了這些小區車流量的資料,那麼就可以根據這個資料進行換算作為你的判斷矩陣。
3. 由判斷矩陣計算被比較元素對于該準則的相對權重, 并進行一緻性檢驗(檢驗通過權重才能用)
CR<0.1通過後,三種3方法計算權重:算術平均、幾何平均、特征值法。
建議大家在比賽時三種方法都使用
以往的論文利用層次分析法解決實際問題時,都是采用其中某一種方法求權重,而不同的計算方法可能會導緻結果有所偏差。為了保證結果的穩健性,本文采用了三種方法分别求出了權重後計算平均值,再根據得 到的權重矩陣計算各方案的得分,并進行排序和綜合分析,這樣避免了 采用單一方法所産生的偏差,得出的結論将更全面、更有效。
注:
- 一緻矩陣不需要進行一緻性檢驗,隻有非一緻矩陣的判斷矩陣才需要進 行一緻性檢驗;
- 在論文寫作中,應該先進行一緻性檢驗,通過檢驗後再計算 權重,視訊中講解的隻是為了順應計算過程
當CR>0.1時如何修正?
名額X | 城市A | 城市B | 城市C |
城市A | 1 | 2 | 1 |
城市B | 1/2 | 1 | 2 |
城市C | 1 | 1/2 | 1 |
答:往一緻矩陣上調整,一緻矩陣的行列成倍數關系
是以:
名額X | 城市A | 城市B | 城市C |
城市A | 1 | 2 | 4 |
城市B | 1/2 | 1 | 2 |
城市C | 1/4 | 1/2 | 1 |
4. 根據權重矩陣計算最終得分,并進行排序。
三、層次分析法的一些局限性
1. 評價的決策層不能太多,太多的話n會很大,判斷矩陣和 一緻矩陣差異 可能會很大。
我們上面提到過的RI名額也隻到了15:
n | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
R | 0.52 | 0.89 | 1.12 | 1.26 | 1.36 | 1.41 | 1.46 | 1.49 | 1.52 | 1.54 | 1.56 | 1.58 | 1.59 |
2. 如果決策層中名額的資料是已知的,那麼我們如何利用這些資料來使得評價的更加準确呢?
層次分析法中,實際情況下沒有坤坤幫我們回答,層次分析法中這張表是交給‘專家’ 填的。(誰比誰重要啊,重要程度是幾呀... ),其實我們自己憑感覺填(兩兩比較的結果)。
該方法仍具有較強的主觀性,判斷/比較矩陣的構造在一定程度上是憑感覺決定的,一緻性檢驗隻是檢驗 感覺 有沒有自相沖突得太離譜。
四、模型拓展
1. 多個準則層:
與之前做法一樣,不過是多算幾組表格。
2. 準則不對應全部方案:
可以把另一個方案的權重設為0
*3. 一個準則隻對應自己的方案
我們隻要生成這樣的表即可:
先成大的部分的判斷矩陣,再分别處理小的。
感覺這個模型還是很簡單的。如果有不了解的地方可以聯系帥氣的部落客。
五、代碼展示
你要購買一台筆記本電腦,要考慮其:顔值、性能、口碑、重量、保險情況,這5個方面,最終篩選出了3種品牌的電腦。
第一步:
确定了目标層、準則層、方案層後,我們要做的就是填下表:
權重 | 電腦A | 電腦B | 電腦C |
顔值 | |||
性能 | |||
口碑 | |||
重量 | |||
保險情況 |
第二步:
我們先處理第一列(權重),其判斷矩陣如下。
顔值 | 性能 | 口碑 | 重量 | 保險情況 | |
顔值 | 1 | 1/2 | 4 | 3 | 3 |
性能 | 2 | 1 | 7 | 5 | 5 |
口碑 | 1/4 | 1/7 | 1 | 1/2 | 1/3 |
重量 | 1/3 | 1/5 | 2 | 1 | 1 |
保險情況 | 1/3 | 1/5 | 3 | 1 | 1 |
matrix = np.array([[1, 1 / 2, 4, 3, 3], [2, 1, 7, 5, 5], [1 / 4, 1 / 7, 1, 1 / 2, 1 / 3], [1 / 3, 1 / 5, 2, 1, 1],
[1 / 3, 1 / 5, 3, 1, 1]])
下面我就以上面這個判斷矩陣為例子,定義權重類:
代碼1:
- 隻定義了權重求解類,初始化時要傳入一個判斷矩陣。
- 往往我們層次分析問題要求解多個判斷矩陣,可以自己在這基礎之上定義一個AHP類,初始化時把全部判斷矩陣都放進去,直接内部計算輸出選擇方案。
import numpy as np
# 計算權重類
# 首先初始化判斷矩陣,檢驗其CR是否<0.1,如果小于則計算權重,否則提示調整矩陣内數值。
class Calculate_weights:
# 初始化判斷矩陣
def __init__(self, array):
self.array = array
# n為矩陣次元
self.n = array.shape[0]
# 矩陣的特征值和特征向量
self.eig_val, self.eig_vector = np.linalg.eig(self.array)
# 矩陣的最大特征值
self.max_eig_val = np.max(self.eig_val)
# 矩陣最大特征值對應的特征向量
self.max_eig_vector = self.eig_vector[:, np.argmax(self.eig_val)].real
# 矩陣的一緻性名額CI
self.CI_value = (self.max_eig_val - self.n) / (self.n - 1)
# 平均随機一緻性名額RI值清單,用于一緻性檢驗。
self.RI_list = [0, 0, 0.52, 0.89, 1.12, 1.26, 1.36, 1.41, 1.46, 1.49, 1.52, 1.54, 1.56, 1.58,
1.59]
# 矩陣的一緻性比例CR
self.CR_value = self.CI_value / (self.RI_list[self.n - 1])
# 一緻性判斷 傳回布爾類型
def test_consist(self):
# 列印矩陣的一緻性名額CI和一緻性比例CR
# 進行一緻性檢驗判斷
if self.n == 2 or self.CR_value < 0.1: # 二階矩陣或CR值小于0.1,可以通過一緻性檢驗。
return True
else: # CR值大于0.1, 一緻性檢驗不通過。
print("判斷矩陣的CR值為:" + str(self.CR_value) + ",未通過一緻性檢驗。")
return False
# 算術平均法求權重
def cal_weight_by_arithmetic_method(self):
# 求矩陣的每列的和
col_sum = np.sum(self.array, axis=0)
# 将判斷矩陣按照列歸一化
array_normed = self.array / col_sum
# 計算權重向量
array_weight = np.sum(array_normed, axis=1) / self.n
# 列印權重向量
print("算術平均法計算得到的權重為:\n", array_weight)
# 傳回權重向量的值
return array_weight
# 幾何平均法求權重
def cal_weight_by_geometric_method(self):
# 求矩陣的每列的積
col_product = np.product(self.array, axis=1)
# 将得到的積向量的每個分量進行開n次方
array_power = np.power(col_product, 1 / self.n)
# 将列向量歸一化
array_weight = array_power / np.sum(array_power)
# 列印權重向量
print("幾何平均法計算得到的權重為:\n", array_weight)
# 傳回權重向量的值
return array_weight
# 特征值法求權重
def cal_weight_by_eigenvalue_method(self):
# 将矩陣最大特征值對應的特征向量進行歸一化處理就得到了權重
array_weight = self.max_eig_vector / np.sum(self.max_eig_vector)
# 列印權重向量
print("特征值法計算得到的權重為:\n", array_weight)
# 傳回權重向量的值
return array_weight
if __name__ == "__main__":
# 給出判斷矩陣
matrix = np.array([[1, 1 / 2, 4, 3, 3], [2, 1, 7, 5, 5], [1 / 4, 1 / 7, 1, 1 / 2, 1 / 3], [1 / 3, 1 / 5, 2, 1, 1],
[1 / 3, 1 / 5, 3, 1, 1]])
# 權重對象
weights_obj = Calculate_weights(matrix)
if weights_obj.test_consist():
# 算術平均法求權重
weight1 = weights_obj.cal_weight_by_arithmetic_method()
# 幾何平均法求權重
weight2 = weights_obj.cal_weight_by_geometric_method()
# 特征值法求權重
weight3 = weights_obj.cal_weight_by_eigenvalue_method()
算術平均法計算得到的權重為: [0.26228108 0.47439499 0.0544921 0.09853357 0.11029827] 幾何平均法計算得到的權重為: [0.2636328 0.47726387 0.05307416 0.09883999 0.10718918] 特征值法計算得到的權重為: [0.26360349 0.47583538 0.0538146 0.09806829 0.10867824]
很明顯,性能要更重要一些:
是以我們填完了表的第一列:
權重 | 電腦A | 電腦B | 電腦C |
顔值 | 0.2636 | ||
性能 | 0.4758 | ||
口碑 | 0.0538 | ||
重量 | 0.0980 | ||
保險情況 | 0.1086 |
其它列同理。
代碼2:
- AHP類,初始化時把全部判斷矩陣都放進去,直接内部計算輸出選擇方案。
總之要學會變通。
import numpy as np
# 計算權重類
# 首先初始化判斷矩陣,檢驗其CR是否<0.1,如果小于則計算權重,否則提示調整矩陣内數值。
class Calculate_weights:
# 初始化判斷矩陣
def __init__(self, array):
self.array = array
# n為矩陣次元
self.n = array.shape[0]
# 矩陣的特征值和特征向量
self.eig_val, self.eig_vector = np.linalg.eig(self.array)
# 矩陣的最大特征值
self.max_eig_val = np.max(self.eig_val)
# 矩陣最大特征值對應的特征向量
self.max_eig_vector = self.eig_vector[:, np.argmax(self.eig_val)].real
# 矩陣的一緻性名額CI
self.CI_value = (self.max_eig_val - self.n) / (self.n - 1)
# 平均随機一緻性名額RI值清單,用于一緻性檢驗。
self.RI_list = [0, 0, 0.52, 0.89, 1.12, 1.26, 1.36, 1.41, 1.46, 1.49, 1.52, 1.54, 1.56, 1.58,
1.59]
# 矩陣的一緻性比例CR
self.CR_value = self.CI_value / (self.RI_list[self.n - 1])
# 一緻性判斷 傳回布爾類型
def test_consist(self):
# 列印矩陣的一緻性名額CI和一緻性比例CR
# 進行一緻性檢驗判斷
if self.n == 2 or self.CR_value < 0.1: # 二階矩陣或CR值小于0.1,可以通過一緻性檢驗。
return True
else: # CR值大于0.1, 一緻性檢驗不通過。
print("判斷矩陣的CR值為:" + str(self.CR_value) + ",未通過一緻性檢驗。")
return False
# 算術平均法求權重
def cal_weight_by_arithmetic_method(self):
# 求矩陣的每列的和
col_sum = np.sum(self.array, axis=0)
# 将判斷矩陣按照列歸一化
array_normed = self.array / col_sum
# 計算權重向量
array_weight = np.sum(array_normed, axis=1) / self.n
# 列印權重向量
#print("算術平均法計算得到的權重為:\n", array_weight)
# 傳回權重向量的值
return array_weight
# 幾何平均法求權重
def cal_weight_by_geometric_method(self):
# 求矩陣的每列的積
col_product = np.product(self.array, axis=1)
# 将得到的積向量的每個分量進行開n次方
array_power = np.power(col_product, 1 / self.n)
# 将列向量歸一化
array_weight = array_power / np.sum(array_power)
# 列印權重向量
#print("幾何平均法計算得到的權重為:\n", array_weight)
# 傳回權重向量的值
return array_weight
# 特征值法求權重
def cal_weight_by_eigenvalue_method(self):
# 将矩陣最大特征值對應的特征向量進行歸一化處理就得到了權重
array_weight = self.max_eig_vector / np.sum(self.max_eig_vector)
# 列印權重向量
#print("特征值法計算得到的權重為:\n", array_weight)
# 傳回權重向量的值
return array_weight
class AHP:
def __init__(self, *args):
self.col = args[0]
self.row = args[1]
self.array = args[2:]
# 初始化最終矩陣
self.finally_matrix = np.empty((len(self.row),len(self.col),))
# 生成全部填好後的最終矩陣
def f_matrix(self):
# matrix 為每個判斷矩陣,記得注意順序,如權重在第一列。
col = 0
row = 0
for matrix in self.array:
weights_obj = Calculate_weights(matrix)
if weights_obj.test_consist():
# 特征值法求權重
weight3 = weights_obj.cal_weight_by_eigenvalue_method()
if col == 0: # 權重的權重放在列(豎着放在第一列)
self.finally_matrix[:, col] = weight3
col += 1
else: # 剩下的都放在行(每行橫着放)
self.finally_matrix[row, col:] = weight3
row += 1
return self.finally_matrix
def result(self):
self.f_matrix()
res = []
for i in range(len(self.col)-1):
tem_res = np.sum(self.finally_matrix[:,0]*self.finally_matrix[:,i+1])
res.append(tem_res)
return res
if __name__ == "__main__":
# 給出判斷矩陣
col = ['權重', '電腦A', '電腦B', '電腦C']
row = ['顔值', '性能', '口碑', '重量', '保險']
weighting = np.array(
[[1, 1 / 2, 4, 3, 3], [2, 1, 7, 5, 5], [1 / 4, 1 / 7, 1, 1 / 2, 1 / 3], [1 / 3, 1 / 5, 2, 1, 1],
[1 / 3, 1 / 5, 3, 1, 1]])
appearance = np.array([[1, 2, 5], [1 / 2, 1, 2], [1 / 5, 1 / 2, 1]])
performance = np.array([[1, 1 / 3, 1 / 8], [3, 1, 1 / 3], [8, 3, 1]])
public_praise = np.array([[1, 1, 3], [1, 1, 3], [1 / 3, 1 / 3, 1]])
weight = np.array([[1, 3, 4], [1 / 3, 1, 1], [1 / 4, 1, 1]])
insurance = np.array([[1, 1, 1 / 4], [1, 1, 1 / 4], [4, 4, 1]])
score_result = AHP(col, row, weighting, appearance, performance, public_praise, weight, insurance).result()
print('選擇{}'.format(col[np.argmax(score_result)+1]))
選擇電腦C。