用Double-DQN方法解决简单迷宫寻路问题

2023-11-11

环境描述:25*25离散的栅格图,起点左上角,终点右下角,障碍物1*1随机分布,动作空间维度2:向右,向下。每次移动奖励-1,遇到障碍物或移动出环境奖励-100,到终点奖励20.  

 

 注:针对这个任务期望SARSA、Q-learning等方法能够快速有效完成,用DQN方法试了很长时间loss都不收敛,猜测应该是训练不够;DoubleDQN方法也训练了很长时间,关键点在于epsilon探索了不能够下降太快。

代码:

import torch
from torchviz import make_dot, make_dot_from_trace
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
import pandas as pd
from Map import Map
import matplotlib.pyplot as plt
import math
env = Map()
class DQNReplayer:
    def __init__(self, capacity):
        self.memory = pd.DataFrame(index=range(capacity),
                columns=['observation', 'action', 'reward',
                'next_observation', 'done'])
        self.i = 0
        self.count = 0
        self.capacity = capacity

    def store(self, *args):
        self.memory.loc[self.i] = args
        self.i = (self.i + 1) % self.capacity
        self.count = min(self.count + 1, self.capacity)

    def sample(self, size):
        indices = np.random.choice(self.count, size=size)
        return (np.stack(self.memory.loc[indices, field]) for field in
                self.memory.columns)

class Net(nn.Module):
    def __init__(self, ):
        super(Net, self).__init__()
        # 设置全连接层,线性映射,y=xA+b,这里输入[batch-size,N-states]二维张量,输出[batch-size,50]的二维张量
        self.fc1 = nn.Linear(2, 32)
        # initializationz按正态初始化,均值方差(0,0.1)
        self.fc1.weight.data.normal_(0, 0.1)
        # 输入[batch-size,50]二维张量,输出[batch-size,N-states]的二维张量
        self.out = nn.Linear(32, 2)
        self.out.weight.data.normal_(0, 0.1)  # initialization

    # 两层线性网络

    def forward(self, x):
        x = self.fc1(x)
        x = F.relu(x)  # 经过一层网络后再经过激活函数
        actions_value = self.out(x)
        return actions_value  # 动作价值


class DQNAgent:
    def __init__(self, env, gamma=0.95,
             replayer_capacity=10000, batch_size=64):

        self.action_n = env.action_space.n
        self.gamma = gamma
        self.batch_size = batch_size
        self.replayer = DQNReplayer(replayer_capacity) # 经验回放
        self.evaluate_net = Net()
        self.target_net=Net()
        self.optimizer = torch.optim.Adam(self.evaluate_net.parameters(), lr=0.001)
        self.lossfunc=torch.nn.MSELoss()
    def learn(self, observation, action, reward, next_observation, done,count):

        self.replayer.store(observation, action, reward, next_observation,done)# 存储经验

        if count%50==0 :
            self.target_net.load_state_dict(self.evaluate_net.state_dict())

        if count>self.batch_size:
            observations, actions, rewards, next_observations, dones = \
                    self.replayer.sample(self.batch_size) # 经验回放
            batch_s=torch.FloatTensor(observations)
            batch_a=torch.LongTensor(actions)
            batch_r=torch.FloatTensor(rewards)
            batch_s_=torch.FloatTensor(next_observations)
            batch_a=torch.unsqueeze(batch_a,dim=-1)
            batch_r=torch.unsqueeze(batch_r,dim=-1)

            '''q = self.evaluate_net(batch_s_).gather(1, batch_a)  #
            q_target = self.target_net(batch_s_).detach()

            y = batch_r + self.gamma * q_target.max(1)[0].view(self.batch_size, 1)   # shape (batch, 1)'''
            q_next=self.target_net(batch_s_).detach()
            q_eval=self.evaluate_net(batch_s)
            q_target=q_eval.clone()
            batch_index = np.arange(self.batch_size, dtype=np.int32)
            q_target[batch_index, batch_a]=batch_r+self.gamma * q_next.max(1)[0].view(self.batch_size,1)

            loss = self.lossfunc(q_eval,q_target)
            self.optimizer.zero_grad()
            loss.backward()
            self.optimizer.step()
        else:
            loss=0
        #if done: # 更新目标网络
            #self.target_net.set_weights(self.evaluate_net.get_weights())

        return loss

    def decide(self, observation,count): # epsilon贪心策略
        #epsilon=cal_epsilon(count)
        epsilon=0.01
        if np.random.rand() < epsilon:
            return np.random.randint(self.action_n)
        s=torch.unsqueeze(torch.FloatTensor(observation), 0)
        actions_value = self.evaluate_net.forward(s)
        # 找出actionsvalue张量每行最大值并返回索引,然后索引的张量放在cpu上再转换成numpy
        action = torch.max(actions_value, 1)[1].data.cpu().numpy()
        action = action[0]
        return action

agent=DQNAgent(env)

class DoubleDQNAgent:
    def __init__(self, env, gamma=0.95,
             replayer_capacity=10000, batch_size=64):

        self.action_n = env.action_space.n
        self.gamma = gamma
        self.batch_size = batch_size
        self.replayer = DQNReplayer(replayer_capacity) # 经验回放
        self.evaluate_net = Net()
        self.target_net=Net()
        self.optimizer = torch.optim.Adam(self.evaluate_net.parameters(), lr=0.001)
        self.lossfunc=torch.nn.MSELoss()
    def learn(self, observation, action, reward, next_observation, done,count):

        self.replayer.store(observation, action, reward, next_observation,done)# 存储经验

        if count%50==0 :
            self.target_net.load_state_dict(self.evaluate_net.state_dict())

        if count>self.batch_size:
            observations, actions, rewards, next_observations, dones = \
                    self.replayer.sample(self.batch_size) # 经验回放
            batch_s=torch.FloatTensor(observations)
            batch_a=torch.LongTensor(actions)
            batch_r=torch.FloatTensor(rewards)
            batch_s_=torch.FloatTensor(next_observations)
            batch_a=torch.unsqueeze(batch_a,dim=-1)
            batch_r=torch.unsqueeze(batch_r,dim=-1)

            '''q = self.evaluate_net(batch_s).gather(1, batch_a)  #
            q_target = self.target_net(batch_s_).detach()

            y = batch_r + self.gamma * q_target.max(1)[0].view(self.batch_size, 1)   # shape (batch, 1)'''

            '''with torch.no_grad:
                q_next=self.target_net(batch_s_).detach()

                action_value=self.evaluate_net(batch_s_)
                action=action_value.max(1)[1].view(self.batch_size,1)
                q_target=q_eval.clone()
                batch_index = np.arange(self.batch_size, dtype=np.int32)
                q_target[batch_index, batch_a]=batch_r+self.gamma * q_next[batch_index,action]'''

            q_eval=self.evaluate_net(batch_s)
            next_eval_qs=self.evaluate_net(batch_s_)
            next_actions=torch.squeeze(next_eval_qs.max(1)[1].view(self.batch_size,1))
            #print(next_actions)
            next_qs=self.target_net(batch_s_).detach()
            next_max_qs=next_qs[np.arange(self.batch_size),next_actions]
            #print(next_max_qs)


            us=torch.LongTensor(rewards)+self.gamma*next_max_qs*(1.-dones)
            us=us.float()
            targets=self.evaluate_net(batch_s)
            #print(us.dtype)
            #print(targets[np.arange(self.batch_size),torch.LongTensor(actions)].dtype)
            targets[np.arange(self.batch_size),actions]=us
            loss = self.lossfunc(q_eval,targets)
            self.optimizer.zero_grad()
            loss.backward()
            self.optimizer.step()
        else:
            loss=0
        #if done: # 更新目标网络
            #self.target_net.set_weights(self.evaluate_net.get_weights())

        return loss

    def decide(self, observation,count): # epsilon贪心策略
        epsilon=cal_epsilon(count)
        #epsilon=0.01
        if np.random.rand() < epsilon:
            return np.random.randint(self.action_n)
        s=torch.unsqueeze(torch.FloatTensor(observation), 0)
        actions_value = self.evaluate_net.forward(s)
        # 找出actionsvalue张量每行最大值并返回索引,然后索引的张量放在cpu上再转换成numpy
        action = torch.max(actions_value, 1)[1].data.cpu().numpy()
        action = action[0]
        return action

agent2=DoubleDQNAgent(env)

def cal_epsilon(count):
    epsilon_start=0.8
    epsilon_final=0.3
    epsilon_decay=10000
    epsilon=epsilon_final + (epsilon_start - epsilon_final) * math.exp( -1. * count / epsilon_decay)
    #epsilon=0
    return epsilon

def play_qlearning(env,agent,count,train=False):
    episode_reward=0
    observation=env.reset()
    actionlist=[]
    while True:
        action=agent.decide(observation,count)
        next_observation,reward,done,_=env.step(action)
        episode_reward+=reward
        actionlist.append(action)
        if train:
            loss=agent.learn(observation,action,reward,next_observation,done,count)

        if done:
            if reward==20:
                sign=True
                final_state=env.state
                return episode_reward,actionlist,sign,loss,final_state
                break
            else:
                sign=False
                final_state=env.state
                return episode_reward,actionlist,sign,loss,final_state
                break
        observation=next_observation
episodes=5000
episode_rewards=[]
book0={}
total_loss=[]
final_state={}
for episode in range(episodes):

    episode_reward,act,flag,L,f_state=play_qlearning(env,agent2,episode+1,train=True)
    if flag==True:
        print('Finished')
        break
    episode_rewards.append(episode_reward)
    total_loss.append(L)
    present_policy= {str(episode):act}
    final_state_present={str(episode):f_state}
    book0.update(present_policy)
    final_state.update(final_state_present)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用Double-DQN方法解决简单迷宫寻路问题 的相关文章

随机推荐

  • Cocos Creator Android打包 apk

    文章目录 1 引言 2 配置打包环境 2 1 下载Java SDK JDK 2 2 下载NDK 3 配置原生发布环境路径 4 打包发布原生平台 5 构建原生工程 6 通过编译器去编译和运行 7 总述 8 结束语 1 引言 今天事情不是很多抽
  • el-select与el-tree结合使用,实现select框下拉使用树形结构选择数据

    使用el select与el tree 实现如下效果 代码如下 注意点 搜索input框的代码一点放在option上面 不要放在option里面 否则一点击搜索框 下拉框就会收起来 不能使用
  • 05-JVM内存分配机制深度剖析

    上一篇 04 JVM对象创建深度剖析 1 对象栈上分配 我们通过JVM内存分配可以知道JAVA中的对象都是在堆上进行分配 当对象没有被引用的时候 需要依靠GC进行回收内存 如果对象数量较多的时候 会给GC带来较大压力 也间接影响了应用的性能
  • react入门必看攻略

    一 react是什么 react是一个用于构建用户界面的 JavaScript 库 二 使用步骤 安装react 1 安装脚手架 npm i create react app g 2 创建项目 create react app 项目名 3
  • JavaScript 全局

    解释 JavaScript 全局属性和方法可用于创建Javascript对象 JavaScript 全局属性 属性 描述 Infinity 代表正的无穷大的数值 NaN 指示某个值是不是数字值 undefined 指示未定义的值 JavaS
  • 宝塔面板解决跨域

    1 找到宝塔面板配置nginx文件的地方 2 增加如下代码 add header Access Control Allow Origin add header Access Control Allow Methods POST PUT GE
  • 使用git查看修改记录

    查看文件中每行代码的最近一次修改人 git blame file name git blame
  • 判断能否被3,5,7整除

    输入一个整数 判断它能否被3 5 7整除 并输出以下信息 1 能同时被3 5 7整除 直接输出3 5 7 每个数中间一个空格 2 能被其中两个数整除 输出两个数 小的在前 大的在后 例如 3 5或者 3 7或者5 7 中间用空格分隔 3 能
  • 简单的Arima模型自动最优拟合与预测

    昨天用R折腾了一个简单的时间序列数据Arima自动拟合与预测 过程不复杂 但由于用得不多 为了防止忘记 撰文记录 打开R 安装一个叫做 Forecast 的包 每次开启R后 使用之前用 library forecast 加载该包 这里我用传
  • pickle.load,pickle.dump构建Coco数据集labels的pickle文件

    1 效果图 write pickle coco classes pickle done loading coco classes pickle person bicycle car motorcycle airplane bus train
  • OSI七层模型,报文数据包帧详解,tcp三次握手与四次挥手说明,WireShark抓包分析

    目录 浅谈OSI参考模型 七层模型 什么是OSI参考模型 OSI参考模型的划分 OSI模型与TCP IP模型的比较 七层详解 工作流程 TCP IP协议栈 简介 通用协议栈描述 报文 数据报 报文段 数据包 帧的概念 tcp三次握手与四次挥
  • Callable接口详解

    Callable接口详解 Callable 返回结果并且可能抛出异常的任务 优点 可以获得任务执行返回值 通过与Future的结合 可以实现利用Future来跟踪异步计算的结果 Runnable和Callable的区别 1 Callable
  • pg_dump实例详解

    本文转自 http blog chinaunix net uid 354915 id 3504632 html 一 pg dump的用法 数据库的导入导出是最常用的功能之一 每种数据库都提供有这方面的工具 例如Oracle的exp imp
  • 密封类(sealed class)

    密封类 使用关键字 sealed 密封类里面可以有若干个子类 这些子类如果要继承密封类 则必须和密封类在同一个文件里 sealed class LicenseStatus2 单例继承密封类 object UnQualified Licens
  • 转-如何绘制业务流程图(二)

    转自 http blog jobbole com 22509 本来写完上篇 我发现没有太多必要单纯讨论这一部分内容 因为对于很多人来讲 缺的不是具体的做法 而是做这件事情的意义以及目标性的明确 一旦对这件事情的意义和目标有深刻认同 那自然会
  • JavaScript 扁平化数组转成Tree

    有时候我们得到的数据结构并不是想要的 这个时候就需要对得到的数据进行处理了 比如 我们拿到的是扁平化的数组 但我们要应用在 tree 树形组件或级联选择器组件中 这样的组件要求数据结构是具有层级递进关系的 tree 结构 或者我们并不需要层
  • 【JVM类加载及字节码技术】类加载阶段——加载、链接(一)

    类在JVM中的流程分析 类加载 1 加载 2 链接 2 1 验证 2 2 准备 2 3 解析 总结 类加载 类的生命周期 加载 gt 验证 gt 准备 gt 解析 gt 初始化 gt 使用 gt 卸载 加载阶段 加载 链接阶段 验证 准备
  • DTCC2023第十四届中国数据库大会分享:MySQL性能诊断平台:利用eBPF技术实现高效的根因诊断

    主题 8月16 18日 DTCC2023第十四届中国数据库大会在北京国际会议中心召开 17日下午在云原生数据库开发与实践分论坛 我将带来分享 MySQL性能诊断平台 利用eBPF技术实现高效的根因诊断 敬请期待 欢迎大家提前试用我们发布的产
  • 5种CSS3鼠标悬停图片显示文字信息

    下载地址 5种CSS3鼠标悬停图片显示文字信息是一款鼠标悬停特效 含5种不同风格的鼠标悬停图片显示文字信息 dd
  • 用Double-DQN方法解决简单迷宫寻路问题

    环境描述 25 25离散的栅格图 起点左上角 终点右下角 障碍物1 1随机分布 动作空间维度2 向右 向下 每次移动奖励 1 遇到障碍物或移动出环境奖励 100 到终点奖励20 注 针对这个任务期望SARSA Q learning等方法能够