昨天以 GridWorld 說明提到如何使用原始定義,以及蒙地卡羅的想法,實現計算狀態價值的方法。今天我們要針對昨天所說的內容進行實作。
我們一樣以之前提到的 GridWorld 為例,我們這邊先討論單一狀態、單次模擬怎麼進行。事實上完成單一狀態、單次模擬的實作後,剩下的讓電腦跑完所有的情況。
首先,我們回顧一下我們手邊的參數
其中,動作是這個模擬實驗中唯一具有隨機性的參數,我們一樣設定採取任一動作的機率相同。實作內容如下:
def Simulating(state, gamma, reward, trans_mat):
value = 0
counter = 0
terminal = False
ShowPath(state)
time.sleep(1)
while not terminal:
action = np.random.randint(0,4)
next_state = np.argmax(trans_mat[:, state, action])
value += reward[next_state]*pow(gamma, counter)
counter += 1
state = next_state
ShowPath(next_state)
print('step: ' + str(counter) + ',action: ' + str(action) +', state: ' +str(state) + ', value: ' + str(value))
if state == 0 or state == 15:
terminal = True
if counter > 50:
return counter, terminal, value
time.sleep(1)
return counter, terminal, value
以上提供的程式,是單次模擬的 function,其中有兩個中止條件。
關於第二點移動次數的限制,現在這個問題下,這個條件可以不要設定的。但是隨著問題越來越複雜,若這個狀態本身是價值很低的狀態,那麼可能會有走不到終點的情況,因此會設定這樣強制中止的條件。
其他的部份相較於之前動態規劃的 Policy Evalution 與 Policy Improvement 的矩陣運算。這邊的只是數字加加減減的計算,因此這裡不多做說明。
ShowPath 可以幫助顯示在 GridWorld 中的移動軌跡
def ShowPath(state):
os.system('cls' if os.name == 'nt' else 'clear')
position = np.full(16,'_')
position[state] = '*'
print('='*20)
print('[Now State]')
position[state] = '*'
print(position.reshape(4,4))
print('='*20)
在 main function 中,設定好參數就可以開始進行模擬了
def main():
## environment setting
# initial state
InitState = 1
# reward function
FuncReward = np.full(16,-1)
FuncReward[0] = 0
FuncReward[15] = 0
# transition matrix
T = np.load('./gridworld/T.npy')
# parameters
gamma = 0.99
# Run
Simulating(InitState, gamma, FuncReward, T)
這邊進行一次模擬,得到結果如下:
====================
[Now State]
[['*' '_' '_' '_']
['_' '_' '_' '_']
['_' '_' '_' '_']
['_' '_' '_' '_']]
====================
step: 15,action: 1, state: 0, value: -13.12541872310217
藉由這樣的方式,在進行多次試驗後,可以得到平均的狀態價值,作為之前動作判斷的依據。