強化學習小案例(十九)
強化學習的小案例:
假設有一個表格,4*4的,想要從其中的一個點到達左上角的點和右下角的點。
比如這樣一個表格,想要從中間其中的一個點到達左上角的點,(0,0)或者是右下角的點(3,3)。
首先先要創造一個環境。
'''
建立一個格子世界
'''
import numpy as np
from gym.envs.toy_text import discrete
#設定方向
UP = 0
RIGHT = 1
DOWN = 2
LEFT = 3
class GridWorldEnv(discrete.DiscreteEnv):
def __init__(self , shape = [4,4]):
self .shape = shape
self.nS = np.prod(self.shape)
self.nA = 4
Max_y = shape[0]
Max_x = shape[1]
p = {}
grid = np.arange(self.nS).reshape(shape)
it = np.nditer(grid , flags = ['multi_index'])
while not it.finished:
s = it.iterindex
y , x = it.multi_index
p[s] = {a : [] for a in range(self.nA)}
is_done = lambda s :s == 0 or s == (self.nS - 1)
reward = 0.0 if is_done(s) else -1.0
if is_done(s):
p[s][UP] = [(1.0 , s , reward , True)]
p[s][RIGHT] = [(1.0 , s , reward , True)]
p[s][DOWN] = [(1.0 , s , reward , True )]
p[s][LEFT] = [(1.0 , s , reward , True)]
else:
np_UP = s if y == 0 else s - Max_x
np_RIGHT = s if x == (Max_x - 1) else s + 1
np_DOWN = s if y == (Max_y - 1) else s + Max_x
np_LEFT = s if x == 0 else s - 1
p[s][UP] = [(1.0 , np_UP , reward , is_done(np_UP))]
p[s][RIGHT] = [(1.0 , np_RIGHT , reward , is_done(np_RIGHT))]
p[s][DOWN] = [(1.0 , np_DOWN , reward , is_done(np_DOWN))]
p[s][LEFT] = [(1.0 , np_LEFT , reward , is_done(np_LEFT))]
pass
it.iternext()
pass
self.p = p
pass
先設定向上右下左走的標識。然後就是要設定一個類來初始化環境了。
下面是程式碼的解釋:
self.shape = shape
self.nS = np.prod(self.shape)
self.nA = 4
Max_y = shape[0]
Max_x = shape[1]
np.prod函式是乘法,比如傳進去[4,5,6],那麼就是120。而這裡傳進去的就是4,4,得到6就是代表元素的個數了。然後Max_y和Max_x得到橫排和豎排的個數。
p = {}
grid = np.arange(self.nS).reshape(shape)
it = np.nditer(grid , flags = ['multi_index'])
grid是建立一個4x4的表格,而np.nditer是為這個表格索引排序。索引完之後就是得到了0,1,2,3,4,5,6,7等等。while not it.finished:
s = it.iterindex
y , x = it.multi_index
p[s] = {a : [] for a in range(self.nA)}
is_done = lambda s :s == 0 or s == (self.nS - 1)
reward = 0.0 if is_done(s) else -1.0
s得到的就是一個索引值,比如(0,0)號就得到0,(0,1)就得到1,以此類推,換行的話繼續相加。y , x就是得到x,y的座標了。比如(1,3)就是得到y = 1,x = 3。p[s]其實每一個格子可以走或者是走之後的狀態,每一個格子有四種走法,上右下左,每一個走法又有下一個狀態,獎勵值。所以一個格子有四種狀態。is_done就是是否到達終點。reward就是獎勵,除了終點,其他點都是負數的獎勵。if is_done(s):
p[s][UP] = [(1.0 , s , reward , True)]
p[s][RIGHT] = [(1.0 , s , reward , True)]
p[s][DOWN] = [(1.0 , s , reward , True)]
p[s][LEFT] = [(1.0 , s , reward , True)]
else:
np_UP = s if y == 0 else s - Max_x
np_RIGHT = s if x == (Max_x - 1) else s + 1
np_DOWN = s if y == (Max_y - 1) else s + Max_x
np_LEFT = s if x == 0 else s - 1
p[s][UP] = [(1.0 , np_UP , reward , is_done(np_UP))]
p[s][RIGHT] = [(1.0 , np_RIGHT , reward , is_done(np_RIGHT))]
p[s][DOWN] = [(1.0 , np_DOWN , reward , is_done(np_DOWN))]
p[s][LEFT] = [(1.0 , np_LEFT , reward , is_done(np_LEFT))]
pass
最後就是一個賦值操作了。第一個是概率值,因為預設所有的行為都是一樣的,所以直接給相同即可,因為以後會根據期望值來進行選擇最高。第二個就是下一個狀態,下一個狀態其實不是一個準確的類別,在這裡就是代表到達下一個的位置,因為如果is_done為True就是到達了終點,那麼沒有下一個狀態了。而reward就是一個獎勵,在上幾行程式碼有講。最後就是是否到達終點,到達就是True,否則就是False。
最後不要忘記迭代器指下一個,否則一直都是0的。
之後就是迭代進行優化獎勵矩陣了。
需要一直更新,不斷迭代。
整體程式碼:
''' 移動測試 ''' import numpy as np from learning.GridWorld import GridWorldEnv env = GridWorldEnv() def value_iteration(env , theta = 0.001 , discount = 0.7): def one_step(state , v): A = np.zeros(env.nA) for a in range(env.nA): for prob, next_state, reward, done in env.p[state][a]: A[a] += prob * (reward + discount * v[next_state]) return A v = np.zeros(env.nS) while True: delta = 0 for s in range(env.nS): A = one_step(s , v) best_action = np.max(A) delta = max(delta , np.abs(best_action - v[s])) v[s] = best_action if delta < theta: break pass # Create a deterministic policy using the optimal value function policy = np.zeros([env.nS, env.nA]) for s in range(env.nS): # One step lookahead to find the best action for this state A = one_step(s , v) best_action = np.argmax(A) # Always take the best action policy[s, best_action] = 1.0 return policy, v policy , v = value_iteration(env) print(np.reshape(np.argmax(policy, axis=1), env.shape)) print(np.reshape(v , [4,4]))
首先當然是得到環境了。
def value_iteration(env , theta = 0.001 , discount = 0.7): def one_step(state , v): A = np.zeros(env.nA) for a in range(env.nA): for prob, next_state, reward, done in env.p[state][a]: A[a] += prob * (reward + discount * v[next_state]) return A
之後就是一個迭代更新了。env就是環境,theta就是迭代停止的條件,discount就是一個折扣值,也就是未來的期望對當前結果的影響。one_step函式就是得到一個表格的各個方向的期望。然後取一個最大的值作為方向。v[next_state]就是下一個狀態的值了。這個值是要不斷更新的。
v = np.zeros(env.nS) while True: delta = 0 for s in range(env.nS): A = one_step(s , v) best_action = np.max(A) delta = max(delta , np.abs(best_action - v[s])) v[s] = best_action if delta < theta: break pass
接下來就是開始迴圈了。
delta就是差值,差值要小於theta。
不斷迭代,best_action就是得到最好的一個方向。
# Create a deterministic policy using the optimal value function policy = np.zeros([env.nS, env.nA]) for s in range(env.nS): # One step lookahead to find the best action for this state A = one_step(s , v) best_action = np.argmax(A) # Always take the best action policy[s, best_action] = 1.0 return policy, v policy , v = value_iteration(env) print(np.reshape(np.argmax(policy, axis=1), env.shape)) print(np.reshape(v , [4,4]))
最後就是得到輸出了。
就是每個位置走的方向了。比如在(0,1)點。3是意思就是向下走。
這個就是一個v,也就是未來期望的一個權值,不斷更新過後的最終值。
# Create a deterministic policy using the optimal value function policy = np.zeros([env.nS, env.nA]) for s in range(env.nS): # One step lookahead to find the best action for this state A = one_step(s , v) best_action = np.argmax(A) # Always take the best action policy[s, best_action] = 1.0 return policy, v policy , v = value_iteration(env) print(np.reshape(np.argmax(policy, axis=1), env.shape)) print(np.reshape(v , [4,4]))