馬爾科夫決策過程
概念與公式
1.收穫:一個馬爾科夫過程中從某一狀態開始直到終止狀態時所有獎勵的有衰減之和(R爲獎勵,gamma爲衰減係數)。
2.價值:馬爾科夫獎勵過程中狀態收穫的期望。
3.價值函數:價值函數建立了從狀態到價值的映射。
4.貝爾曼方程:它提示一個狀態的價值由該狀態的獎勵以及後續狀態價值按概率分佈求和按一定的衰減比例聯合組成。
貝爾曼方程可以寫成矩陣形式
求解得的式子可以用矩陣計算得出某狀態的價值。
5.策略:在給定狀態下從行爲集中選擇一個行爲的依據。是某一狀態下基於行爲集合的一個概率分佈。
6.最優狀態價值函數:所有策略下產生的衆多狀態價值函數中的最大者。
7.最優行爲價值函數:所有策略下產生的衆多行爲價值函數中的最大者。一旦找到最優行爲函數,最優策略就找到了。
8.一個狀態的最優價值是該狀態下所有行爲對應的最有行爲價值的最大值。可以通過後續可能狀態的最優價值計算得到。
9.一個行爲的最優價值可由該行爲可能進入的所有後續狀態的最優狀態價值來計算得到。
代碼實現
import numpy as np
num_states = 7
i_to_n = {} #索引到狀態名的字典{‘0’:‘C1’,...,'3':'PASS','4':'PUB','5':'FB','6':'SLEEP'}
i_to_n["0"] = "C1"
i_to_n["1"] = "C2"
i_to_n["2"] = "C3"
i_to_n["3"] = "Pass"
i_to_n["4"] = "Pub"
i_to_n["5"] = "FB"
i_to_n["6"] = "Sleep"
n_to_i = {} #狀態名到索引的字典
for i,name in zip(i_to_n.keys(),i_to_n.values()):
n_to_i[name] = int(i)
Pss = [ # 狀態轉移概率矩陣
[ 0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0 ],
[ 0.0, 0.0, 0.8, 0.0, 0.0, 0.0, 0.2 ],
[ 0.0, 0.0, 0.0, 0.6, 0.4, 0.0, 0.0 ],
[ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0 ],
[ 0.2, 0.4, 0.4, 0.0, 0.0, 0.0, 0.0 ],
[ 0.1, 0.0, 0.0, 0.0, 0.0, 0.9, 0.0 ],
[ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0 ]
]
Pss = np.array(Pss)
#獎勵函數,分別與狀態對應
rewards = [-2,-2,-2,10,1,-1,0]
gamma = 0.5 #衰減因子
def compute_return(strat_index = 0,chain = None,gamma = 0.5):
'''求一個馬爾科夫獎勵過程的收穫
start_index 要計算的狀態在鏈中的位置
chain 要計算的馬爾科夫過程
gamma 衰減係數
ret 收穫值
'''
ret ,power,gamma = 0.0,0,gamma
for i in range(strat_index,len(chain)):
ret += np.power(gamma,power)*rewards[n_to_i[chain[i]]]
power += 1
return ret
chains =[
["C1", "C2", "C3", "Pass", "Sleep"],
["C1", "FB", "FB", "C1", "C2", "Sleep"],
["C1", "C2", "C3", "Pub", "C2", "C3", "Pass", "Sleep"],
["C1", "FB", "FB", "C1", "C2", "C3", "Pub", "C1", "FB","FB", "FB", "C1", "C2", "C3", "Pub", "C2", "Sleep"]
]
def compute_value(Pss,rewards,gamma):
'''求解矩陣得到狀態價值(page7)
:param Pss:狀態轉移概率矩陣
:param rewards:獎勵
:param gamma:衰減因子
:return:價值矩陣
'''
# reshape():-1爲缺省值,可自動從另一個參數和已知維度推算
rewards = np.array(rewards).reshape((-1,1)) #變爲一列
#np.dot():矩陣乘法
#inv():求逆矩陣
#np.eye():單位矩陣
values = np.dot(np.linalg.inv(np.eye(7,7) - gamma*Pss),rewards) #由公式計算
return values
print(compute_return(0, chains[3], gamma = 0.5))
print(compute_value(Pss, rewards, gamma = 0.99999))