部分专有名词在上一篇文章有介绍,本文不作过多赘述。
Q-Learning是强化学习演算法中value-based的演算法,Q即为Q(s,a),就是在某一个时刻的state状态下,采取动作a能够获得收益的期望,环境会根据agent的动作反馈相应的reward奖赏,所以演算法的主要思想就是将state和action构建成一张Q_table表来存储Q值,然后根据Q值来选取能够获得最大收益的动作。
Q-Learning
state
agent
reward
action
Q_table
Q-learning的主要优势就是使用了时间差分法(融合了蒙特卡洛和动态规划)能够进行off-policy的学习,使用贝尔曼方程可以对马尔科夫过程求解最优策略,本文对其中演算法不进行推导,会另外写一篇推导的文章。
我们还是用一开始举的做作业的例子来说明:
参数介绍
Epsilon greedy
alpha
gamma
背景
在一个一维时间,在世界的右边有宝藏,探险者只要得到宝藏尝到了甜头,以后就会记住得到宝藏的方法,这就是他用强化学习所学习到的行为。
o
left/right
Q(s,a)
行为准则
预设参数
import numpy as np import pandas as pd import time
np.random.seed(2) # reproducible
N_STATES = 6 #一维世界的宽度 ACTIONS = [left,right] #探索者可用的动作 EPSILON = 0.9 #greedy贪婪度 ALPHA = 0.1 #学习率 GAMMA = 0.9 #奖励递减值 MAX_EPISODES = 13 #最大回合数 FRESH_TIME = 0.3 #每回合移动间隔时间
Q表
我们要将所有Q values放在q_table中,更新q_table也是在更新他的行为准则。q_table的index是所有对应的state(o所在的位置),columns是对应的action(探险者选择left或者right)
Q values
q_table
index
state(o所在的位置)
columns
action(探险者选择left或者right)
def build_q_table(n_states, actions): table = pd.DataFrame( np.zeros((n_states, len(actions))), # q_table 全 0 初始 columns=actions, # columns 对应的是行为名称 ) return table
# q_table: """ left right 0 0.0 0.0 1 0.0 0.0 2 0.0 0.0 3 0.0 0.0 4 0.0 0.0 5 0.0 0.0 """
定义action
接著定义探险者是如何挑选行为的,这就是我们引入epsilon greedy的概念。因为在初始阶段,随机的探索环境,往往比固定的行为模式要好,所以这也是累积经验的阶段,我们希望探险者不那么贪婪(greedy),所以EPSILON就是用来控制贪婪程度的值。EPSILON可以随著探险时间不断提升(越来越贪婪),不过在这个例子中,我们就固定EPSILON=0.9,90%的时间是选择最优策略,10%的时间来探索。
epsilon greedy
(greedy)
EPSILON
def choose_action(state, q_table): state_actions = q_table.iloc[state, :] # 选出这个state的所有 action的value值 if (np.random.uniform() > EPSILON) or (state_actions.all() == 0): #非贪婪 or 或者这个 state 还没有探索过 action_name = np.random.choice(ACTIONS) else: action_name = state_actions.idxmax() # 贪婪模式 return action_name
环境的反馈S_,R
做出行为后,环境也要给我们的行为一个反馈,反馈出下一个state(S_)和上一个state(S)做出action(A)所得到的reward(R)。这里定义的规则是,只有当o移动到了T(探险者获取了宝藏),探险者才会得到唯一的奖励,奖励值R=1,其他情况没有奖励。
state(S_)
state(S)
action(A)
reward(R)
T
def get_env_feedback(S,A): if A== right: #往右探险 if S == N_STATES - 2: #找到宝藏 S_ = terminal R = 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_STATES-1) + [T] # ---------T our environment if S == terminal: interaction = Episode %s: total_steps = %s % (episode+1, step_counter) print( {}.format(interaction), end=) time.sleep(2) print( , end=) else: env_list[S] = o interaction = .join(env_list) print( {}.format(interaction), end=) time.sleep(FRESH_TIME)
强化学习的主循环
最重要的地方就是这里,将刚才理论部分我们讲解到的演算法实现出来。
def rl(): q_table = bulid_q_table(N_STATES,ACTIONS) #初始化q_table 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_feedback(S,A) #实施行为并得到环境的反馈 q_predict = q_table.loc[S,A] #估算的(状态-行为)值 if S_ != terminal: q_target = R + GAMMA*q_table.iloc[S_,:].max() #实际的(状态-行为)值 else: q_target = R #实际的(状态-行为值) is_terminated = True
q_table.loc[S,A] += ALPHA*(q_target - q_predict) #q_table更新 S = S_ #更新探索者位置
update_env(S,episode,step_counter+1)
step_counter += 1 return q_table
结果
我们可以看到,一开始没有任何经验的探险者需要非常多次的尝试才能找到宝藏,而随著探险次数的增多,最后就可以自己走到宝藏的地方了。
参考:
推荐阅读: