实现步骤:
- 随机生成一个Q表,初始化状态为S0;
- 在当前状态下选择一个动作执行:如果Q表全为0,随机选择。否则,10%的时间随机选择一个动作执行,90%的时间选择当前状态下,使得Q值最大的一个动作A执行;
- 根据当前状态和当前动作,获得下一个会产生的状态S_和奖励R;(此步根据现实自定义)
- 根据选择的动作,计算预估的Q值(即查Q表),真实的Q值 Q_real = R+lambda*max(Q(S'),即reward再加上后续状态中出现的最大的Q值。具体原理类似于贝尔曼方程;
- 更新Q表,Q(S,A) = Q(S,A) + alpha * ( Q_real - Q_predict)
- 重复上述步骤,直到满足预设的条件。
- 重复进行上述学习步骤,多回合更新Q表。
学习自:【莫烦Python】强化学习 Reinforcement Learning_哔哩哔哩_bilibili
import numpy as np
import pandas as pd
import time
import sys
np.random.seed(2)
N_STATE = 6
ACTIONS = ['left','right']
EPSILON = 0.9
ALPHA = 0.1 #学习率
LAMBDA = 0.9 #衰减因子
MAX_EPISODES =10 #最大回合数
FRESH_TIME = 0.1 #每步的刷新时间
TERMINAL = 4
def build_q_table(n_states,actions):
table = pd.DataFrame(
np.zeros((n_states,len(actions))),
columns=actions, #actions name
)
return table
def choose_action(state,q_table):
state_actions = q_table.iloc[state,:] #取第state行的数据,就是当前state的可能发生的所有actions
if np.random.uniform() > EPSILON or state_actions.all() == 0:
action_name = np.random.choice(ACTIONS) ##初始或者10%的时间 随便选一个action
else:
action_name = ACTIONS[state_actions.argmax()] ##90%的时间选择其中q值最大的一个
return action_name
def get_env_feed_back(S,A):
if A == 'right': #动作为右移,移动到宝藏4的位置终止
if S == N_STATE - 2:
S_ = 'TERMINAL'
R = 1 #找到了宝藏,结束,奖励1
else:
S_ = S+1 #继续右移
R = 0
else: #动作为左移
R=0
if S == 0:
S_ = S #碰到墙了
else :
S_ = S -1 #没碰到墙,继续左移
return S_,R
def update_env(S, episode,step_counter):
env_list = ['-'] * (N_STATE - 1) +['T']
if S == 'TERMINAL':
interaction = 'Episode %s: total_steps = %s' % (episode+1, step_counter)
print('\r{}'.format(interaction),end='')
time.sleep(2)
print('\r ',end='')
else:
env_list[S] = 'o' #探索者的位置
interaction = ''.join(env_list)
print('\r{}'.format(interaction),end='')
time.sleep(FRESH_TIME)
def rl():
q_table = build_q_table(N_STATE,ACTIONS)
for episode in range (MAX_EPISODES):
step_counter = 0
S = 0 #初始探索者的位置在最左边
is_terminated = False
update_env(S,episode,step_counter) #初始化打印一下环境
while not is_terminated:
A = choose_action(S,q_table) #选择一个动作,左移或者右移
S_, R = get_env_feed_back(S,A) #根据选择的动作得到下一个应该转移的状态
#查Q表
q_predict = q_table.loc[S,A]
# 计算Q的真实值 由后续状态的Q值最大的得出
if S_ != 'TERMINAL':
q_target = R + LAMBDA * q_table.iloc[S_,:].max()
else :
q_target = R
is_terminated = True
#更新Q表
q_table.loc[S,A] += ALPHA * (q_target - q_predict)
S = S_
update_env(S,episode,step_counter+1) #继续更新
step_counter += 1
return q_table
if __name__ == '__main__':
q_table = rl()
print(q_table)
效果如下