深度强化学习笔记(二)——Q-learning学习与二维寻路demo实现_q learning 代码例子 demo_没有顶会的咸鱼的博客-程序员秘密

深度强化学习笔记(二)——Q-learning学习与二维寻路demo实现

前言

这几天稍微闲下来,把原来漏的坑给补上,并做了一个Q-Learning的demo,因为Q-leraning的demo,目前我看到比较多的都是莫烦大佬讲的那个一纬寻路的demo,我觉得看起来没有那么有代表性,于是在此基础上,自己修改做了一个二维寻路的demo,奥利给

理论

什么是Q-Learning

Q-learning是一种无模式RL的形式,它也可以被视为异步DP的方法。它通过体验行动的后果,使智能体能够在马尔可夫域中学习以最优方式行动,而无须构建域的映射。智能体在特定状态下尝试行动,并根据其收到的即时奖励或触发以及对其所处状态的值得估计来评估其后果。 通过反复尝试所有状态的所有行动,它可以通过长期折扣奖励来判断总体上最好的行为。

算法

从状态 Δ t \Delta t Δt步进入未来步长的权重计算为 γ Δ t \gamma^{\Delta t} γΔt, γ \gamma γ(折扣因子)是介于0和1,并且具有对较迟收到的奖励(反映出良好开端的价值)进行估值的效果。 γ \gamma γ也可以被解释为在每一步 Δ t \Delta t Δt都成功的概率
Q : S × A − > R Q:S\times A->R Q:S×A>R
首先把Q-learning状态表的动作表初始化为0,然后通过训练更新每个单元。在每个时间t智能体选择动作 a t a_t at,观察奖励 r t r_t rt,进入新状态 s t + 1 s_{t+1} st+1(可能取决于先前状态 s t s_t st和所选的动作),并对Q进行更新 ,该算法的核心是一个简单的值迭代更新过程,即使用旧值和新信息的加权平均值
Q n e w ( s t , a t ) < − ( 1 − α ) Q ( s t , a t ) + α ( r t + γ m a x a Q ( s t + 1 , a ) ) Q^{new}(s_t,a_t)<-(1-\alpha)Q(s_t,a_t)+\alpha(r_t+\gamma max_aQ(s_{t+1},a)) Qnew(st,at)<(1α)Q(st,at)+α(rt+γmaxaQ(st+1,a))
其中, r t r_t rt是从状态 s t s_t st移动到状态 s t + 1 s_{t+1} st+1时收到的奖励, α \alpha α是学习率, Q ( s t , q t ) Q(s_t,q_t) Q(st,qt)为旧值, m a x a Q ( s t + 1 m , a ) max_aQ(s_{t+1}m,a) maxaQ(st+1m,a)为信息

学习率

α \alpha α确定了新获取的信息在多大程度上覆盖旧信息。因子0使得智能体什么都不学习(专门利用先验知识),而因子1使得智能体只考虑最新信息(忽略先验知识,以探索可能性),一般情况下,通常使用恒定的学习率, α t = 0.1 \alpha _t=0.1 αt=0.1

折扣因子

折扣因子\gamma$决定了未来奖励的重要性。因子0将通过仅考虑当前奖励使得智能体近视,而接近1的因子将智能体努力获得长期高奖励。这种情况下,从较低的折扣因子开始并将其增加到最终值会加速学习

初始条件

由于Q-learning是迭代算法嘛,因此它隐含地假定在第一次更新发生之前的初始条件。高初始值,也称为"乐观初始条件",也可以鼓励探索:无论选择何种动作,更新规则将其使具有比其他替代方案更低的值,从而增加其选择概率

例子

原文链接:点我
翻译复制的一个大佬的作品:A Painless Q-learning Tutorial (一个 Q-learning 算法的简明教程)





代码

因为有比较详细的注释,这里就不过多解释了

这里的代码最好在CMD里运行,由于jupyter notebook或者pycharm等IDE无法使用os.system('cls')清楚输出,会导致每次迷宫行动都是单独的一个,而不会在原基础更新,看起来比较难受~
升级版作图,由于IDE也不会更新,只会生成新的图,pycharm会存在生成25张图之后,就不会再生成了,无法看到后续变化,jupyter notebook会生成多张图,但是不容易看
如果有大佬知道解决方案,请私信或者评论里提出,谢谢大佬们

基础版走迷宫示意图


升级版走迷宫示意图

因为我暂时没有想到好的解决方法,大佬们可以自己想下,由于画图会增加内存,而当地图尺寸在5以上的时候,有部分由于随机种子的原因,在还前期训练的时候,有一两次的训练的轮数达到400次左右,导致内存占用过高,而训练图崩溃,大佬们可以想下怎么解决

完整代码

import numpy as np
import pandas as pd
import time
from matplotlib import pyplot as plt
import os

np.random.seed(3) #固定随机种子,方便调试
N_STATES = 3#迷宫的边长
ACTIONS = ['up','down','left', 'right']#动作,上下左右移动
EPSILON = 0.9#随机率,每10次,选择一次新的随机动作
ALPHA = 0.1#学习率
GAMMA = 0.9#折扣率,当折扣率为0时,则只关注当前奖励,而接近1则关注长期奖励
MAX_EPISODES = 20#最大EPISODERS次数
FRESH_TIME = 0.1#移动时间
X=1#初始坐标x
Y=1#初始坐标Y
target_x=3 #宝藏坐标x
target_y=3 #宝藏坐标y
NOW_STATE=0 #当前位置对应的Q表值

#生成初始Q表
#因为边长为N,每个点有上下左右四个选择,则数量为N*N*4
#N:N
#ACTIONS:动作
def build_q_table(N, actions):
    table = pd.DataFrame(
        np.zeros((N*N, len(actions))),
        columns=actions,
    )
    #(table)
    return table

#选择动作
#EPSILON:选择新动作的概率为1-EPSILON
#state:当前的状态位置(已经转换为一维表上的值)
#q_table:Q表
def choose_action(state, q_table):
    state_actions = q_table.iloc[state, :]
    if (np.random.uniform() > EPSILON) or ((state_actions == 0).all()):
        #当前可以选择的动作表得奖励值都为0(即初始表)时,或者当随机数大于EPSILON时,随机选择一个新动作
        action_name = np.random.choice(ACTIONS)
    else:
        #否则选则当前可选动作表里奖励最大的值
        action_name = state_actions.idxmax()
    #返回要选择的动作的名字
    return action_name

#更新当前位置
def get_env_feedback(x,y,A):
    if A == 'up':  #向上移动
        #达到上边界,不做变化
        if y==1:
            y=y
        else:
            y=y-1
    elif A=='down':
        #到达下边界,不做变化
        if y==N_STATES:
            y=y
        else:
            y=y+1
    elif A=='left':
        #到达左边界,不做变化
        if x==1:
            x=x
        else:
            x=x-1
    elif A=='right':
        #到达右边界,不做变化
        if x==N_STATES:
            x=x
        else:
            x=x+1
    R=0
    # 判断是否达到终点,到达则将奖励置于1
    if (x == target_x) and (y==target_y):
        R=1
    return x,y,R

# 若到达宝藏位置,则打印本回合的序号和经历的步数。
# 否则打印本次移动后小人的位置(二维世界的当前状态)
def update_env(x,y,target_x, target_y, episode, step_counter):
    #做一个以+为点的坐标,*为宝藏
    env_list = np.array(['+']*(N_STATES*N_STATES))
    env_list=env_list.reshape(N_STATES,N_STATES)
    #确定是否达到终点
    if (x == target_x) and (y==target_y):
        interaction = 'Episode %s: total_steps = %s' % (episode+1, step_counter)
        print(interaction+'\n', end='')
        time.sleep(2)
        step_counter=0
        return step_counter
    else:
    #若未达到终点
        #老版本0.01显示图像
        env_list[target_x-1][target_y-1]='*'
        env_list[x-1][y-1] = 'o'
        interaction=''
        for a in range(N_STATES):
            interaction1 = ''.join(env_list[a,:])
            interaction1=interaction1+'\n'
            interaction=interaction+interaction1
        print(interaction)
        time.sleep(0.3)
        os.system('cls')
        #升级版迷宫图
        # label_x=np.array(range(N_STATES))
        # label_y=np.array(range(N_STATES))
        # label_x = label_x.reshape(N_STATES, 1)
        # label_x = np.tile(label_x, (1, N_STATES))
        # label_x = label_x.reshape(N_STATES*N_STATES)
        # label_y = np.tile(label_y, (N_STATES, 1))
        # label_y = label_y.reshape(N_STATES*N_STATES)
        # plt.ion()
        # plt.cla()
        # plt.plot(label_x, label_y, 'x', markersize=10)
        # plt.plot(x-1, y-1, 'o', markersize=20)
        # plt.plot(target_x-1, target_y-1, 's', markersize=20)
        # plt.show()
        # plt.pause(0.01)
        return step_counter-1

# 强化学习主要的控制器
#step_counter:记录该次episode运行了多少次
#is_terminated:是否是终点
def rl(X_1,Y_1,target_x,target_y):
    #c创建初始化零值表
    q_table = build_q_table(N_STATES, ACTIONS)
    #循环最大次数
    step_counter = 0
    for episode in range(MAX_EPISODES):
        X=X_1
        Y=Y_1
        is_terminated = False
        step_counter=update_env(X,Y,target_x,target_y,episode, step_counter)
        #如果不是终点,则进行循环
        while not is_terminated:
            #当前状态为第x列第y行对应的值
            NOW_STATE=int((Y*EPSILON-1)+X-1)
            A = choose_action(NOW_STATE, q_table)
            #更新当前位置,进行行为并获取奖励和下一次的状态
            X_,Y_,R = get_env_feedback(X,Y, A)
            q_predict = q_table.loc[NOW_STATE, A]
            #确定是否达到终点
            if (X_ != target_x) or (Y_!=target_y):
                NOW_STATE_ = int((Y_ * EPSILON-1) + X_-1)
                q_target = R + GAMMA * q_table.iloc[NOW_STATE_, :].max()
            else:
                q_target = R
                is_terminated = True
            #更新Q表
            q_table.loc[NOW_STATE, A] += ALPHA * (q_target - q_predict)
            #移动到下一个状态
            X=X_
            Y=Y_
            #打印状态
            step_counter=update_env(X,Y,target_x,target_y, episode, step_counter+1)
            step_counter += 1
    return q_table
if __name__ == "__main__":
    q_table = rl(X,Y,target_x,target_y)
    print('\r\nQ-table:\n')
    print(q_table)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/InkBamboo920/article/details/107867977

智能推荐

UnityShader18:立方体贴图(上)_Jaihk662的博客-程序员秘密

一、天空盒使用立方体贴图最直接的目的就是展现天空盒,或者更进一步用于实现环境映射(反射与折射)关于立方体贴图的采样原理:https://blog.csdn.net/Jaihk662/article/details/107379399Unity 中天空盒的设置:一样可以对于不同的摄像机使用不同的天空盒:二、简单的反射实现关于反射和折射的原理:https://blog.csdn.net/Jaihk662/article/details/107491144代码和效果...

Android 快速用RxJava2做倒计时_JackLittlePig的博客-程序员秘密

绕过概述原理,直接上代码:public class RxCountDown { public static Observable countdown(int time) { if (time 0) time = 0; final int countTime = time; return Observable.interval(0, 1

CDN防DDoS攻击_JPshangdexiaofeixia的博客-程序员秘密

随着近年来来网络技术的不断进步,cdn已经不只简单的用做网站加速,还能够更好的保护网站不被攻击。Cdn在相关节点中成功的建立动态加速机制以及智能沉于等机制,这种机制能够帮助网站流量访问分配到每一个节点中,智能的进行流量分配机制,如果cdn存在被ddos攻击的情况。Cdn整个系统就能够将被攻击的流量分散开,节省了站点服务器的压力以及节点压力。同时还能够增强网站被黑客给攻击的难度。真正帮助服务管理人员

数据库学习过程_数据库过程_嫌疑人X的替身的博客-程序员秘密

一.有关mariadb切换到root用户 su -root 查看本地是否安装了mariadb的状态 rpm -qa | grep mariadb 查看mariadb的状态 servicemariadbstatus 启动mariadb servicemariadbstart 关闭mariadb servicemariadbstop二.MySQL启动时MySQL数据库启动时,会先启动一个守护进程.守护进程在判断MySQL服务器是否...

学习汇编前你应该知道的知识_陈伟chenwei的博客-程序员秘密

1、汇编需要什么工具和程序,到哪里下载?    目前阶段,汇编程序仅需要两个程序就够了。masm.exe,link.exe。 前者是编译程序,后者是链接程序。另外,为了验证和调试程序,还需要一个程序debug.exe,该程序由windows本身就提供。    将二者下载后,放到某一个目录中(任意目录都可以),考虑到很多命令需要通过键盘敲入,所以建议你不要把文件放入到长文件名目录、中

随便推点

Kinect v2.数据源与获取_Osean_li的博客-程序员秘密

引言在Kinect for windows SDK2.0中,Kinect有多种类型的数据源。Source,Reader和Frame。要读取骨架,就有IBodyFrameSource, IBodyFrameReader, IBodyFrame这三个类,要读取深度数据,就有IDepthFrameSource, IDepthFrameReader, IDepthFrame这三个类在Kinect...

九度 1482 玛雅人的密码_leobean18的博客-程序员秘密

1482 玛雅人的密码http://ac.jobdu.com/problem.php?pid=1482 http://ac.jobdu.com/oldexamset.php玛雅人有一种密码,如果字符串中出现连续的2012四个数字就能解开密码。给一个长度为N的字符串,(2<= N <=13)该字符串中只含有0,1,2三种数字,问这个字符串要移位几次才能解开密码,每次只能移动相邻的两个数字。例如021

php-fpm配置文件详解_php-fpm 路径_Asnfy的博客-程序员秘密

php-fpm主配置文件路径:/usr/local/php-fpm/etc/php-fpm.conf#位于安装php安装目录下的etc/目录中,该文件中最后一行将配置文件指向:include=/usr/local/php-fpm/etc/php-fpm.d/*.confphp-fpm子配置文件路径:/usr/local/php-fpm/etc/php-fpm.d/www.conf#php所有...

用PHP开发购物车网站(第三篇):零碎知识(1)_HorseRunningNoStop的博客-程序员秘密

ceil:向上取整数limit:用于在数据库查询时限定选择的记录区间,eg:order by id (asc) limit(4,2);这时数据表是正序排列(id从小到大),limit的意思是(从正序排列的第5条数据开始取2条)order by id desc limit(4,2);这时数据表是倒序排列(id从大到小),limit的意思是(从倒

程序员都在用的软件,你都知道哪几个?_木木之叶的博客-程序员秘密

刚开始工作的小白程序员都特别苦恼工作效率不高的问题,下面这七个我收藏的上手快,简单实用的效率软件新手程序员一定不能错过!typora typora是一个优质的Markdown编辑器,使用这个软件可以轻松写出一篇具有良好的排版和可读性的文章。Typora支持markdown的标准语法。除了文字之外,斜体、加粗、插入图片、引用、插入图片、代码、表格、有序列表等等操作就在你敲完代码的一瞬间出现在编辑器上了,直接能看到Markdown 最终的排版效果。AlfredAlfred是M...

推荐文章

热门文章

相关标签