層次分析法---python實現
層次分析法(The analytic hierarchy process)簡稱AHP
在20世紀70年代中期由美國運籌學家托馬斯·塞蒂(T.L.saaty)正式提出。它是一種定性和定量相結合的、系統化、層次化的分析方法。由於它在處理複雜的決策問題上的實用性和有效性,很快在世界範圍得到重視。它的應用已遍及經濟計劃和管理、能源政策和分配、行為科學、軍事指揮、運輸、農業、教育、人才、醫療和環境等領域。
比較常用的場合是進行決策,層次分析法是一種比較常見的多目標決策方法。其實我看來,層次分析法就是一種按照層次結構計算加權和的方法,主要是權重的選取,這裡人為因素太大,比較容易受到詬病。
具體的理論,可以參考wiki
層次分析法的多級遞階層次模型分為三類:完全相關性結構、完全獨立性結構、混合型結構。
前兩種分別對應於下圖的圖1,2(來自網路,侵刪):
圖1 . 完全相關性
圖2. 完全獨立性
混合型就是具備兩種的特點。其實也不需要管這個了,就是按照自己的需要搭建好層次結構就可以了,有了結構下面開始擼程式碼。
示例:
此次我們實現的是這樣的層次結構,如圖3,同時我們假設成對比較矩陣已經按照尺度表定義好(尺度表即表示相對權重,在wiki中可以找到),實際應用中可以根據需求求解成對比較矩陣。
圖3. 示例的層次結構圖
python3 程式碼。
# -*- coding: utf-8 -*-
"""
Created on Tue Nov 13 15:37:12 2018
@author: user
"""
"""
AHP demo: 第一層:A, 第二層:B1 B2 B3, 第三層:C1 C2 C3, 完全相關性結構。
"""
import numpy as np
"""
1. 成對比較矩陣
"""
def comparision(W0): # W為每個資訊值的權重
n=len(W0)
F=np.zeros([n,n])
for i in range(n):
for j in range(n):
if i==j:
F[i,j]=1
else:
F[i,j]=W0[i]/W0[j]
return F
"""
2. 單層排序,相對重要度
"""
def ReImpo(F):
n=np.shape(F)[0]
W=np.zeros([1,n])
for i in range(n):
t=1
for j in range(n):
t=F[i,j]*t
W[0,i]=t**(1/n)
W=W/sum(W[0,:]) # 歸一化 W=[0.874,2.467,0.464]
return W.T
"""
3. 一致性檢驗
"""
def isConsist(F):
n=np.shape(F)[0]
a,b=np.linalg.eig(F)
maxlam=a[0].real
CI=(maxlam-n)/(n-1)
if CI<0.1:
return bool(1)
else:
return bool(0)
"""
4. 計算綜合重要性
"""
def ComImpo(W12,W231,W232,W233): # 綜合重要性
#F12=comparision(W12) # 實際應用中可以根據特徵的權重求解成對比較矩陣。
#F231=comparision(W231)
#F232=comparision(W232)
#F233=comparision(W233)
F12=np.array([[1,1/3,2],[3,1,5],[1/2,1/5,1]]) # 此處直接假設出成對比較矩陣
F231=np.array([[1,1/3,1/5],[3,1,1/3],[5,3,1]])
F232=np.array([[1,2,7],[1/2,1,5],[1/7,1/5,1]])
F233=np.array([[1,1/3,1/7],[3,1,1/5],[7,5,1]])
if isConsist(F12) and isConsist(F231) and isConsist(F232) and isConsist(F233):
W12=ReImpo(F12)
W231=ReImpo(F231)
W232=ReImpo(F232)
W233=ReImpo(F233)
W23=np.hstack([W231,W232,W233])
else:
print("成對比較矩陣不一致,請調整權重後重試!")
return 0
n=len(W12)
C=np.zeros([1,n])
for i in range(n):
t=W23[i,:]
C[0,i]=sum((W12.T*t)[0])
return C
def main():
print("這裡是AHP的演示程式:")
w=np.ones([3]) # W 為成對比較矩陣
C=ComImpo(w,w,w,w)
print('最佳方案為第',np.argmax(C)+1,'個方案.','綜合推薦指數為',max(C[0,:]))
if __name__ == '__main__':
main()
# print(__name__)