【强化学习】Q-Learning算法详解以及Python实现【80行代码】

强化学习

在文章正式开始前,请不要被强化学习的tag给吓到了,这也是我之前所遇到的一个困扰。觉得这个东西看上去很高级,需要一个完整的时间段,做详细的学习。相反,强化学习的很多算法是很符合直观思维的。 因此,强化学习的算法思想反而会是相当直观的。

另外,需要强调的是,这个算法在很多地方都有很详细的阐述了。这篇文章的工作,很多也是基于前辈的工作而继续推进的。这里也引用方便后来者进一步学习。这里再次感谢前辈的工作,确实对我有较大的帮助。

Q-Learning

这个算法异常的简单。
虽然可能存在非常多的改进点 or 存在大量的应用场景下的不兼容,但又有点基石的感觉,还是值得学习一下,感受其中的思想的。

简单来说,就是维护一张Q表

  • Q表,存储的表记录的是,在状态S下,每个行为A的Q值。

一般的更新的公式
Q [ S , A ] = ( 1 − α ) ∗ Q [ S , A ] + α ∗ ( R + γ ∗ m a x Q [ S n e x t , : ] ) Q[S, A] = (1-\alpha)*Q[S, A] + \alpha*(R + \gamma * max{Q[S_{next}, :]}) Q[S,A]=(1α)Q[S,A]+α(R+γmaxQ[Snext,:])

对于下一步是终点的更新公式
Q [ S , A ] = ( 1 − α ) ∗ Q [ S , A ] + α ∗ R Q[S, A] = (1-\alpha)*Q[S, A] + \alpha*R Q[S,A]=(1α)Q[S,A]+αR

  • 也很容易理解,一般的更新公式 多出一个项的原因是,对于下一步不是终点的状态,这一步的奖励R一般来说是0,拿不到直接的奖励。但是又需要记录该节点的该操作在未来的可能贡献。因此这里引用对未来的预测。

有一说一,还挺像动态规划的,这么想想,是不是觉得这个算法,初、高中生其实也都可以学会?

Q表

Q表示是一个矩阵。

  1. 分别表示,在所有的可能 状态 下,各个可能的 行为 下的Q值
  2. 使用方式,有 ϵ \epsilon ϵ的概率,或者该状态下的Q表还是初始状态,则随机选择一个操作进行状态转移( 这个操作有个好听的名字, ϵ \epsilon ϵ-greedy );
  3. 如果没有进行 随机状态转移 , 那么就在该状态下,选Q值最大的 行为

到这里,对算法应该是有基本的概念。

接下来的问题是,如何对Q表更新呢?
也就是,所谓的Q-Learning

Q表更新

想法非常直观。
如果在最后一步,选择对了,那么是不是就是给上一个状态的所执行的ACTION有个比较好的奖励。比如,奖励R=1

那有个问题,按照上面的更新的话,倒数第二步,或者那些让整个比赛没办法直接结束的状态,就没办法得到了奖励。

为了解决这个问题。Q中,加入了一个预测的概念。

即,对于那些没有办法直接获得奖励的状态,他的奖励更新(或者是叫Q表更新),会基于该状态下,执行该操作之后的 新的状态的所有操作中的最大Q值来更新
当然也许本次操作本身也是有对应奖励,这就另外说了。

具体算法是:

  1. 新状态对应任务结束了,获取了奖励。q_predict=1
  2. 新状态对应的任务没有结束,那就用新状态的最大Q值来更新。q_predict=R+GAMMA*q_table[S_New].max(),其中R表示该操作本身的奖励,算是个局部信息,GAMMA表示这种预测的信息的传递损失。很自然的设计,算是为了避免陷入局部最优解。
  3. 还需要引入一个学习率ALPHA的概念,这个学过深度学习or机器学习的都会觉得很自然的了。q_table[S, A] += ALPHA * (q_predict - q_table[S, A])。同样也是为了避免陷入局部最优的问题。

至此,算法讲完了。是不是很简单

实现

  • 这里参考mofan大佬用到的一个treasure on right的弱智游戏来实现Q-Learning这个算法。
    • 这个游戏就是,宝藏在最右边的位置。然后训练一个智能体去获得这个宝藏。(说智能体,有点贴金了)
  • 这里,我对代码做了简单优化。另外也简单解释一下各个参数吧。
  • N_STATES 表示状态数量。其实就是位置数量。
  • EPSILON就是 ϵ \epsilon ϵ-greedy ϵ \epsilon ϵ
  • 同理,ALPHA,GAMMA也类似
  • MAX_EPISODES 表示玩多少轮游戏来训练。
  • FRESH_TIME是用来输出的参数,控制多久刷新一次页面之类。(用来好看的)
  • TerminalFlag 用来记录游戏结束的标志符,方便统一,就放在外面。
import time

import numpy as np
import pandas as pd

N_STATES = 6
ACTIONS = ["left", "right"]
EPSILON = 0.9
ALPHA = 0.1
GAMMA = 0.9
MAX_EPISODES = 15
FRESH_TIME = 0.3
TerminalFlag = "terminal"


def build_q_table(n_states, actions):
    return pd.DataFrame(
        np.zeros((n_states, len(actions))),
        columns=actions
    )


def choose_action(state, q_table):
    state_table = q_table.loc[state, :]
    if (np.random.uniform() > EPSILON) or ((state_table == 0).all()):
        action_name = np.random.choice(ACTIONS)
    else:
        action_name = state_table.idxmax()
    return action_name


def get_env_feedback(S, A):
    if A == "right":
        if S == N_STATES - 2:
            S_, R = TerminalFlag, 1
        else:
            S_, R = S + 1, 0
    else:
        S_, R = max(0, S - 1), 0
    return S_, R


def update_env(S, episode, step_counter):
    env_list = ["-"] * (N_STATES - 1) + ["T"]
    if S == TerminalFlag:
        interaction = 'Episode %s: total_steps = %s' % (episode + 1, step_counter)
        print(interaction)
        time.sleep(2)
    else:
        env_list[S] = '0'
        interaction = ''.join(env_list)
        print(interaction)
        time.sleep(FRESH_TIME)


def rl():
    q_table = build_q_table(N_STATES, 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_feedback(S, A)
            q_predict = q_table.loc[S, A]

            if S_ != TerminalFlag:
                q_target = R + GAMMA * q_table.loc[S_, :].max()
            else:
                q_target = R
                is_terminated = True
            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)

  • 47
    点赞
  • 217
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
机器⼈python路径规划_基于Q-learning的机器⼈路径规划系统 (matlab) 0 引⾔ Q-Learning算法是由Watkins于1989年在其博⼠论⽂中提出,是强化学习发展的⾥程碑,也是⽬前应⽤最为⼴泛的强化学习算法。Q- Learning⽬前主要应⽤于动态系统、机器⼈控制、⼯⼚中学习最优操作⼯序以及学习棋类对弈等领域。 1 项⽬概述 Q学习在机器⼈路径规划领域有较为⼴泛的应⽤,由于其只需要与环境进⾏交互,且仅需感知当前状态和环境即可对下⼀步动作进⾏决策。 本研究以 MATLAB为基础,设计基于Q学习的最短路径规划算法,并考虑智能体的斜 向运动,更加符合实际情况。同时使⽤DQN⽹络对Q 值更新进⾏⼀定的优 化,使得Q值表能够更加符合实际应⽤。 本次研究的具体步骤如下: 设计⼀个有障碍物的地图,⽤户可以修改障碍物布局,可以指定起点和终点; 使⽤MATLAB编程实现Q-learning算法,⽤于机器⼈规划最短路径,学习算法参数可以由⽤户设置; 使⽤⽤可视化界⾯演⽰Q值变化过程及最短路径探测过程。 2 Q-learning算法思想 Q-Learning算法是⼀种off-policy的强化学习算法,⼀种典型的与模型⽆关的算法算法通过每⼀步进⾏的价值来进⾏下⼀步的动作。基于 QLearning算法智能体可以在不知道整体环境的情况下,仅通过当前状态对下⼀步做出判断。 Q-Learning强化学习算法中value-based的算法,Q是指在某⼀时刻的某⼀状态下采取某⼀动作期望获得的收益。环境会根据智能体的动 作反馈相 应的回报,所以算法的主要思想就是将状态与动作构建成⼀张Q值表,然后根据Q值来选取能够获得最⼤的收益的动作。 3 算法步骤 (⼀)Q-学习步骤 初始化Q值表。构造⼀个n⾏n列(n为状态数)的 Q值表,并将表中的所有值初始化为零。 基于当前Q值表选取下⼀个动作a。初始状态时,Q值 均为零,智能体可有很⼤的选择空间,并随机选择下⼀步动作。随着迭代次数增 加,Q值表不断更新,智能体 将会选择回报最⼤的动作。 计算动作回报。采⽤动作a后,根据当前状态和奖励,使⽤Bellman ⽅程更新上⼀个状态的Q(s, t)。 NewQ(s,a) = (1 α)Q(s,a) + α(R(s,a) + γmaxQ (s ,a )) 其中, NewQ(s,a)——上⼀个状态s和动作a的新Q值 Q(s,a)——当前状态s和动作a的Q值 R(s,a)——当前状态s和动作a的奖励r maxQ (s ,a )——新的状态下所有动作中最⼤的Q值 重复步骤3,直到迭代结束,得到最终的Q值表。 根据Q值表选择最佳路径。 (⼆)算法改进 避免局部最优 Q-learning本质上是贪⼼算法。如果每次都取预期奖励最⾼的⾏为去 做,那么在训练过程中可能⽆法探索其他可能的⾏为,甚⾄会进 ⼊"局部 最优",⽆法完成游戏。所以,设置系数,使得智能体有⼀定的概率采取 最优⾏为,也有⼀定概率随即采取所有可采取的⾏动。 将⾛过的路径纳⼊ 记忆库,避免⼩范围内的循环。 增加斜向运动 将斜向运动的奖励值设置为 2/ 2 ,取近似值0.707,可以避免出现如机器 ⼈先向左上⽅移动再向左下⽅移动⽽不选择直接向左移动两格 的情况。设 置为此值是根据地图的两格之间的相对距离确定的。 4 MATLAB实现代码 %% 基于Q-learning算法的机器⼈路径规划系统 clear %% ⾸先创造⼀个机器⼈运动的环境 % n是该运动的运动环境的矩阵environment(n,n)的⾏列⼤⼩ n = 20; % 新建⼀个全为1的n*n维environment矩阵 environment = ones(n,n); %下⾯设置环境中的障碍物,将其在矩阵中标为值-100(可⾃⾏设置障碍物) environment(2,2:5)=-100; environment(5,3:5)=-100; environment(4,11:15)=-100; environment(2,13:17)=-100; environment(7,14:18)=-100; environment(3:10,19)=-100; environment(15:18,19)=-100; environment(3:10,19)=-100; environment(3:10,7)=-100; environment(9:19,2)=-100; environment(15:17,7)=-100; environment(10,3:7)=-100; environment(13,5:8)=-100; environment(6:8,4)=-100; environment(13:18,4)=-100; environment(6
由于联邦学习优化算法是一个较为复杂的问题,需要考虑到多个方面的因素,因此在这里只给出一个简单的示例代码,仅供参考。 首先,我们需要定义一个状态空间和动作空间。在联邦学习优化算法中,状态空间可以包括当前轮次、本地数据集大小、本地计算能力等因素;动作空间可以包括本地训练轮次、本地学习率等因素。 接下来,我们需要定义一个q-table来存储每个状态下的动作价值。在每次训练时,根据当前状态选择一个动作,并更新q-table中相应的价值。 最后,我们可以根据q-table中的价值来选择最优的动作来更新模型参数。具体实现代码如下: ```python import numpy as np # 定义状态空间和动作空间 state_space = [i for i in range(10)] action_space = [i for i in range(10)] # 定义q-table,初始化为0 q_table = np.zeros((len(state_space), len(action_space))) # 定义超参数 epsilon = 0.1 alpha = 0.5 gamma = 0.9 num_episodes = 1000 # 定义环境模型 def environment(state, action): # 计算奖励函数 reward = state * action # 计算下一个状态 next_state = state + 1 # 判断是否到达终止状态 done = next_state == len(state_space) return reward, next_state, done # 定义Q-learning算法 def q_learning(state, epsilon): # 以epsilon-greedy策略选择动作 if np.random.uniform(0, 1) < epsilon: action = np.random.choice(action_space) else: action = np.argmax(q_table[state]) # 更新q-table reward, next_state, done = environment(state, action) q_table[state, action] += alpha * (reward + gamma * np.max(q_table[next_state]) - q_table[state, action]) return next_state, done # 训练Q-learning算法 for i in range(num_episodes): state = 0 done = False while not done: state, done = q_learning(state, epsilon) # 根据q-table选择最优动作更新模型参数 best_action = np.argmax(q_table[state]) update_model(best_action) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肥宅_Sean

公众号“肥宅Sean”欢迎关注

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值