RL的Q Learning原理及简单算例

1. Q-learning简述

  Q-learning是一种强化学习算法。强化学习指的是让计算机在什么都不懂的情况下,通过不断的和环境进行互动得到反馈,来改善自身的行动策略,最终找到规律并达到学习目的的方法。

  所以强化学习的过程只涉及两个对象,一个是智能体agent,它可以发出行动action,接受反馈并评估;另一个是环境environment,它是agent行动的前提,并能对agent的行动做出反馈。

  Q-learning的核心在于,它有一个记录着不同状态下采取行动所对应价值的表,即Q table。随着不断地行动,得到反馈去更新Q表中的值。所以,一般称Q-learning算法是基于价值即Value-based的。

行动1 行动2
状态1
状态2
状态3

2. Q-learning基本原理

举个例子

  让我们设想这样一个情景,你正在写一篇技术博客,共有5个章节(states)。你可以采取两种行动(actions),一是写,二是躺着休息。

  在前四章选择写时,你获得了烦躁和微妙的成就感(reward),可以设定为0;在第五章选择写时,你达到了最终状态完成这篇文章,得到了内心的平和以及好心人的点赞,可以设为1;当任一状态选择老子不写了可以获得如释重负的愉悦,依旧设定为0。

  可以看出,从reward的角度来看,如果我们只关心当下的感受,写不写都是一样的。Q-learning的高明之处在于,状态-行动产生的Q值(Q table对应值)和之后的状态-行动相关,这样就可以达到延迟满足的目的。

QLearning是怎么learn的

  1. 预估Q值

  首先随机生成一个Q表。假设我们处在第三个状态s3即写完第三章,我们可以选择a1写,a2休息。此时我们观察一下Q table:

a1 a2
s3 0.1 0.2

  此时Q表表明选择a2更好,得到预估的Q(s3,a2)。但在实际编程中为了避免探索-利用困境(exploration-exploitation dilemma),即总是利用已知选最优解而失去了探索新的有可能的最优解。此处使用贪心算法(greedy)设定了一个概率阈值 ϵ \epsilon ϵ,即有 1 − ϵ 1-\epsilon 1ϵ不选Q最大的行动而随机选择。

  1. 实际Q值

  此处实际Q值仅和下一状态-行动Q值及其奖励有关。先假设 Q ( s 1 ) = R 2 + Q ( s 2 ) Q(s1)=R2+Q(s2) Q(s1)=R2+Q(s2)。但我们往往会在下一状态-行动的Q值先增加一个衰减系数 γ \gamma γ,即 Q ( s 1 ) = R 2 + γ Q ( s 2 ) Q(s1)=R2+\gamma Q(s2) Q(s1)=R2+γQ(s2)。当我们把式子从 Q ( s 1 ) Q(s1) Q(s1)展开,我们可以发现:
Q ( s 1 ) = r 2 + γ Q ( s 2 ) = r 2 + γ [ r 3 + γ Q ( s 3 ) ] = r 2 + γ [ r 3 + γ r 4 + γ Q ( s 4 ) ] ] = … \mathbf{Q}(\mathbf{s} \mathbf{1})=\mathbf{r} \mathbf{2}+\gamma \mathbf{Q}(\mathbf{s} \mathbf{2})=\mathbf{r} \mathbf{2}+\gamma[\mathbf{r} \mathbf{3}+\gamma \mathbf{Q}(\mathbf{s} \mathbf{3})]=\mathbf{r} \mathbf{2}+\gamma[\mathbf{r} \mathbf{3}+\gamma \mathbf{r}\mathbf{4}+\gamma \mathbf{Q} \mathbf{( s 4})] \mathbf{]}=\ldots Q(s1)=r2+γQ(s2)=r2+γ[r3+γQ(s3)]=r2+γ[r3+γr4+γQ(s4)]]=
Q ( s 1 ) = r 2 + γ r 3 + γ 2 r 4 + γ 3 r 5 + γ 4 r 6 + … Q(s 1)=r 2+\gamma r 3+\gamma^{2} r 4+\gamma^{3} r 5+\gamma^{4} r 6+\ldots Q(s1)=r2+γr3+γ2r4+γ3r5+γ4r6+
  此时,实际Q值仅和各个状态的奖励有关。衰减系数等于1意味着我们能清清楚楚地看到之后所有步的全部价值,而小于1意味着,越往后的选择带来的奖励对当前行动产生的影响越小。
  回到s3,我们选择了a2,到达了s4。此时我们发现,s4-a2对应Q值更大,故假设选择 m a x Q ( s 4 ) = Q ( s 4 , a 2 ) maxQ(s4)=Q(s4,a2) maxQ(s4)=Q(s4,a2),(注意:此处因为贪心算法对行动的选择具有随机性,是假设而不是真的选择。接下来操作目的是对Q(s3,a2)进行修正(learn),可以使后续选择对当前状态-行动组合产生影响)。同时通过不断的写到达终止状态s5,得到了 R 4 = 1 R4=1 R4=1的奖励。

a1 a2
s4 0.1 0.3

  让我们重新设定Q(s3,a2)的实际值。此时只考虑下一步的奖励和最大Q值,可以用 R + m a x Q ( s 4 ) R+maxQ(s4) R+maxQ(s4)作为新的Q值。

  1. 修正Q值

  在Q-learning算法中,Q值不是一下就改变的,因为后续Q值是未完全修正的,它值作为一种参考意见。我们往往在预估Q的基础上进行修改。 Q 预 估 = Q 预 估 + α ( Q 实 际 − Q 预 估 ) Q预估 = Q预估 + \alpha(Q实际-Q预估) Q=Q+α(QQ),其中 α \alpha α是学习率(learning-rate),越大表明更新越快,等于1时意味着直接替换为Q实际。
这样我们就明白了Q Learning的核心内容Q值的更新(update):
Q ( s , a ) ← Q ( s , a ) + α [ r + γ max ⁡ a ′ Q ( s ′ , a ′ ) − Q ( s , a ) ] Q(s, a) \leftarrow Q(s, a)+\alpha\left[r+\gamma \max _{a^{\prime}} Q\left(s^{\prime}, a^{\prime}\right)-Q(s, a)\right] Q(s,a)Q(s,a)+α[r+γamaxQ(s,a)Q(s,a)]

3. Q Learning简单算例

伪代码

  一个episode是一个回合,包含了初始状态到终止状态的全过程。每一个step是做出行动的一步(状态不一定会变)。每一步查看预估Q值采取行动得到新的状态,假想新状态的行动得到实际Q值,并修正。
 Initialize  Q ( s , a )  arbitrarily   Repeat (for each episode):   Initialize  s  Repeat (for each step of episode):   Choose  a  from  s  using policy derived from  Q  (e.g.,  ε -greedy)   Take action  a ,  observe  r , s ′ Q ( s , a ) ← Q ( s , a ) + α [ r + γ max ⁡ a ′ Q ( s ′ , a ′ ) − Q ( s , a ) ] s ← s ′ ;  until  s  is terminal  \begin{aligned} &\text { Initialize } Q(s, a) \text { arbitrarily } \\ &\text { Repeat (for each episode): } \\ &\quad\text { Initialize } s \\ &\quad\text { Repeat (for each step of episode): } \\ &\quad\quad\text { Choose } a \text { from } s \text { using policy derived from } Q \text { (e.g., } \varepsilon \text {-greedy) } \\ &\quad\quad\text { Take action } a, \text { observe } r, s^{\prime} \\ &\quad\quad Q(s, a) \leftarrow Q(s, a)+\alpha\left[r+\gamma \max _{a^{\prime}} Q\left(s^{\prime}, a^{\prime}\right)-Q(s, a)\right] \\ &\quad\quad s \leftarrow s^{\prime} ; \\ &\quad \text { until } s \text { is terminal } \end{aligned}  Initialize Q(s,a) arbitrarily  Repeat (for each episode):  Initialize s Repeat (for each step of episode):  Choose a from s using policy derived from Q (e.g., ε-greedy)  Take action a, observe r,sQ(s,a)Q(s,a)+α[r+γamaxQ(s,a)Q(s,a)]ss; until s is terminal 

莫烦python的-----T寻宝游戏

参考Github;课程见小例子 - 强化学习 (Reinforcement Learning) | 莫烦Python

  1. 参数设置,Q table初始化
# -*- coding: utf-8 -*-
"""
Created on Wed Dec  1 10:21:54 2021

@author: z
"""

import numpy as np
import pandas as pd
import time

#parameters 参数设置
N_STATES = 6 #states
ACTIONS = ['left','right'] #actions
EPSILON = 0.9 #greedy rate
ALPHA = 0.1 #learning rate
GAMMA = 0.9 #discount factor 奖励衰减值
MAX_EPISODES = 13 #maximum episodes
FRESH_TIME = 0.1 #移动时间间隔 fresh time for one move

  1. 智能体agent初始化、行动和学习

#initialize Q 初始化Q表
def build_Q_table(n_states, actions):
    table = pd.DataFrame(np.zeros((n_states,len(actions))),
                         columns = actions) 
    return table
	
#take action 根据Q表选择行动
def choose_action(state, Q_table):
    s_a = Q_table.iloc[state,:] #?iloc 行号获取数据
    if (np.random.uniform() > EPSILON) or (s_a.all() == 0):#?all parameters
        action_name = np.random.choice(ACTIONS)
    else:
        action_name = s_a.argmax() #?默认索引
    if action_name==1:
        action_name = 'right'
    elif action_name==0:
        action_name = 'left'
    return action_name
	
#learn 更新Q表
def update(S, A, S_, R, Q_table, GAMMA):
    Q_predict = Q_table.loc[S,A] 
    if S_ == 'terminal':
        Q_real = R
        is_terminated = True #!true关键字
    else:
        Q_real = R + GAMMA*Q_table.iloc[S_,:].max()
        is_terminated = False

	# modify after taking action
    Q_table.loc[S,A] += ALPHA * (Q_real - Q_predict)
    return is_terminated

  1. 环境environment初始化(显示)和反馈
#set environment 设置环境 可以用Tkinter或gym
def update_env(S, episode, step_counter):
    # This is how environment be updated
    env_list = ['-']*(N_STATES-1) + ['T']   # '---------T' our environment
    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)

#get feedback 得到反馈包括下一状态和奖励
def get_env_feedback(S,A):
    if A == 'right':
        if S == N_STATES - 2:
            S_ = 'terminal'
            R = 1 #rewards = 1
        else:
            S_ = S+1
            R = 0
    else:
        if S == 0:
            S_ = S
            R = 0
        else:
            S_ = S-1
            R = 0
    return S_, R

  1. 整体实现
#main RL
def rl():
    Q_table = build_Q_table(N_STATES, ACTIONS)
    step = 1000 #记录最终步数,设定比较大的初值
    
    #循环(回合数结束 Q整体更新次数)
    for episode in range(MAX_EPISODES):
        S = 0 #对象参数化
        step_counter = 0
        update_env(S, episode, step_counter)
        
        #循环(知道达到终止状态)
        is_terminated = False
        while not is_terminated:
            A = choose_action(S, Q_table)
            
            S_,R = get_env_feedback(S, A)

            is_terminated = update(S, A, S_, R, Q_table, GAMMA)
            
            S = S_ #!不要忘记更新状态
            update_env(S, episode, step_counter)
            step_counter +=1
        
		#保存当前最优策略(Q)
        if step>=step_counter:
            step = step_counter
            Q_table_final = Q_table
            EP = episode+1
            
    return EP,Q_table_final

if __name__ == "__main__":
    EP,q_table = rl()
    print('\r\nEpisode:%s'%(EP))
    print('\r\nQ-table:\n')
    print(q_table)

你可能感兴趣的:(RL,强化学习)