深度强化学习中利用N-步TD预测算法在随机漫步应用中实战(超详细 附源码)

简介: 深度强化学习中利用N-步TD预测算法在随机漫步应用中实战(超详细 附源码)

需要源码请点赞关注收藏后评论区留下QQ或者私信~~~

一、N-步TD预测

N步TD预测算法在TD(0)和MC之间架起了一座桥梁,而TD(L)算法则能进一步实现两者之间的无缝衔接。下面介绍N步TD预测

N步TD算法更新方式介于TD(0)和MC之间,该类算法利用未来多步奖赏和多部之后的值函数估计求得目标值,例如两步更新就是利用未来两步奖赏和两步之后的值函数估计得到两步回报。N步TD属于TD(时序差分法)当前状态的更新目标是当前Agent采集到的后续n步奖赏与后继第n个状态的带权价值估计之和,与TD(0)不同的是:这里的后继状态是n步后的状态,而不是当前状态的下一个状态

基于状态值函数的N步TD预测算法流程图如下

二、N步TD在随机漫步实例中的应用

背景描述:Agent起始位置为E点,在A点左侧和I点右侧有两个终止位置,即左终点和右终点,Agent从A点向左走到左终点则获得-1的奖赏,从I点向右走到右终点则获得+1的奖赏,其他情况奖赏均为0,除了终点以外,在每个点Agent都可以等概率的采取向左或者向右两个动作,固定学习率为0.5,折扣系数为1,初始化所有状态值为0

示例图如下

下图是对n采取不同的数值来说明N步TD算法的流程,然后讨论n以及学习率对于N步TD算法性能的影响 结果如下图

重复1000次,得到平均结果可以看出在11个状态的随机漫步问题中,n取值略大于1时效果会更好,并且选取介于TD(0)和MC之间的N步TD预测算法会得到更好的结果

同样表明所有的N步TD算法在合适的条件下都能收敛到正确的预测,同时随着n的增加,n步回报相对真实值函数偏差也会越来越小,但是计算需要耗费更多时间和资源,所以要选择合适的n进行偏差和方差之间较好的权衡

代码如下

''' 深度强化学习——原理、算法与PyTorch实战,代码名称:代22-例7.1-n-步TD预测算法在随机漫步实例中的应用.py '''
# 导入相应的模块
from random import random, choice
from myBookEnvCode.my_random_walk import RandomWalkEnv
import matplotlib.pyplot as plt
import math
import numpy as np
import max_min_smooth_py
nums_for_ave = 1000  # 平均1000次
class Agent():
    def __init__(self):
        self.actions = [0, 1]  # 两个动作
        self.aveErrors = {}
        ''' 不同n时的平均均方误差 '''
        self.aveErrors[1] = np.zeros(100)
        self.aveErrors[2] = np.zeros(100)
        self.aveErrors[4] = np.zeros(100)
        self.aveErrors[8] = np.zeros(100)
        self.epErrors = []
    def calc_error(self, ep_num, V):
        ''' 计算平均均方误差 '''
        error = 0
        for i in range(1, 10):
            target = -1 + 0.2 * i
            data = V[i] if i in V.keys() else 0
            error = error + (target - data) * (target - data)
        error = math.sqrt(error / 9)
        self.epErrors[ep_num] = error
    def nStepTDLearning(self, env, n, gamma, alpha, max_episode_num):
        ''' n步Td算法学习 '''
        self.V = {}
        self.epErrors = np.zeros(max_episode_num)
        num_episode = 1
        ''' 运行max_episode_num情节 '''
        while num_episode <= max_episode_num:
            s = env.reset()  # 环境初始化
            if not s in self.V.keys():
                self.V[s] = 0
            a = self.Policy(s, num_episode)  # 选择动作
            time_in_episode = 0
            T_ep = 1000
            ep_states = [s]
            ep_actions = [a]
            ep_rewards = [0]  # 奖赏下标从1开始
            time_update = 0
            while True:
                if time_in_episode < T_ep:
                    n_s, n_r, done, _ = env.step(a)  # 进入下一个状态
                    env.render()
                    if not n_s in self.V.keys():  # 没有访问过的状态,值初始化为0
                        self.V[n_s] = 0
                    ep_states.append(n_s)
                    ep_rewards.append(n_r)
                    if done:
                        T_ep = time_in_episode + 1
                    else:
                        n_a = self.Policy(n_s, num_episode)
                        ep_actions.append(n_a)
                        s = n_s
                        a = n_a
                time_update = time_in_episode - n + 1
                ''' 判断,进行更新 '''
                if time_update >= 0:
                    n_step_return = 0
                    xs = 1
                    for i in range(time_update + 1,
                                   min(time_update + n + 1, T_ep + 1)):
                        n_step_return += xs * ep_rewards[i]
                        xs *= gamma
                    if (time_update + n < T_ep):
                        n_step_return += xs * self.__getVValue(
                            ep_states[time_update + n])
                    ''' 获取旧的v值,更新后写进v表 '''
                    old_v = self.__getVValue(ep_states[time_update])
                    new_v = old_v + alpha * (n_step_return - old_v)
                    self.__setVValue(ep_states[time_update], new_v)
                time_in_episode += 1
                if (time_update == T_ep - 1):
                    break
            self.calc_error(num_episode - 1, self.V)  # 每个情节结束计算一次误差
            num_episode += 1
        self.aveErrors[n][int(alpha * 100) - 1] += sum(
            self.epErrors) / max_episode_num  # 所有情节误差进行平均
        return
    def Policy(self, s, episode_num):
        ''' 定义策略 '''
        a = choice(list(self.actions))  # 左右走概率均等的策略
        return a
    def __getVValue(self, s):  # ①
        ''' V值的获取 '''
        return self.V[s]  # argmax(q)
    def __setVValue(self, s, new_v):  # ②
        ''' V值的设置 '''
        self.V[s] = new_v
def dealData(aveErrors):
    ''' 处理数据 '''
    aveErrors = max_min_smooth_py.max_min_smooth(aveErrors)
    for i in range(len(aveErrors)):
        aveErrors[i] = aveErrors[i] / nums_for_ave
    return aveErrors
def plot_n_alpha(aveErrors):
    ''' 绘制图像 '''
    x_axis = np.linspace(0.01, 1, 100)
    ax = plt.gca()
    ax.spines['top'].set_color('none')
    ax.spines['right'].set_color('none')
    ax.xaxis.set_ticks_position('bottom')  # 用bottom代替x轴
    ax.yaxis.set_ticks_position('left')  # 用left代替y轴
    '''不同n的取值时的平均均方根误差'''
    plt.plot(x_axis,
             dealData(aveErrors[1]),
             color="green",
             ls='-',
             label="$n=1$")
    plt.plot(x_axis,
             dealData(aveErrors[2]),
             color="red",
             ls='--',
             label="$n=2$")
    rors[8]),
             color="blue",
             ls=':',
             label="$n=8$")
    plt.legend()
    plt.xlabel(r"$\alpha$")
    plt.ylabel("平均均方根误差")
    plt.show()
def nStepTDLearningExample(agent, env):
    ''' 取不同学习率进行实验 '''
    x = np.linspace(0.01, 1, 100)
    for alpha_num in x:  # 不同n值的实验结果
        for _ in range(nums_for_ave):
            agent.nStepTDLearning(env=env,
                                  n=1,
                                  gamma=1,
                                  alpha=alpha_num,
                                  max_episode_num=6)
        for _ in range(nums_for_ave):
            agent.nStepTDLearning(env=env,
                                  n=2,
                                  gamma=1,
                                  alpha=alpha_num,
                                  max_episode_num=6)
        for _ in range(nums_for_ave):
            agent.nStepTDLearning(env=env,
                                  n=4,
                                  gamma=1,
                                  alpha=alpha_num,
                                  max_episode_num=6)
        for _ in range(nums_for_ave):
if __name__ == "__main__":
    agent = Agent()
    env = RandomWalkEnv()  # 引入环境env
    print("Learning...")
    nStepTDLearningExample(agent, env)

创作不易 觉得有帮助请点赞关注收藏~~~

相关文章
|
1月前
|
算法 数据可视化 测试技术
HNSW算法实战:用分层图索引替换k-NN暴力搜索
HNSW是一种高效向量检索算法,通过分层图结构实现近似最近邻的对数时间搜索,显著降低查询延迟。相比暴力搜索,它在保持高召回率的同时,将性能提升数十倍,广泛应用于大规模RAG系统。
130 10
HNSW算法实战:用分层图索引替换k-NN暴力搜索
|
1月前
|
机器学习/深度学习 缓存 算法
微店关键词搜索接口核心突破:动态权重算法与语义引擎的实战落地
本文详解微店搜索接口从基础匹配到智能推荐的技术进阶路径,涵盖动态权重、语义理解与行为闭环三大创新,助力商家提升搜索转化率、商品曝光与用户留存,实现技术驱动的业绩增长。
|
2月前
|
运维 监控 JavaScript
基于 Node.js 图结构的局域网设备拓扑分析算法在局域网内监控软件中的应用研究
本文探讨图结构在局域网监控系统中的应用,通过Node.js实现设备拓扑建模、路径分析与故障定位,提升网络可视化、可追溯性与运维效率,结合模拟实验验证其高效性与准确性。
227 3
|
1月前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
2月前
|
机器学习/深度学习 边缘计算 人工智能
粒子群算法模型深度解析与实战应用
蒋星熠Jaxonic是一位深耕智能优化算法领域多年的技术探索者,专注于粒子群优化(PSO)算法的研究与应用。他深入剖析了PSO的数学模型、核心公式及实现方法,并通过大量实践验证了其在神经网络优化、工程设计等复杂问题上的卓越性能。本文全面展示了PSO的理论基础、改进策略与前沿发展方向,为读者提供了一份详尽的技术指南。
粒子群算法模型深度解析与实战应用
|
2月前
|
机器学习/深度学习 算法 安全
小场景大市场:猫狗识别算法在宠物智能设备中的应用
将猫狗识别算法应用于宠物智能设备,是AIoT领域的重要垂直场景。本文从核心技术、应用场景、挑战与趋势四个方面,全面解析这一融合算法、硬件与用户体验的系统工程。
|
1月前
|
机器学习/深度学习 算法 机器人
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
186 0
|
1月前
|
数据采集 分布式计算 并行计算
mRMR算法实现特征选择-MATLAB
mRMR算法实现特征选择-MATLAB
140 2
|
2月前
|
传感器 机器学习/深度学习 编解码
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
192 3
|
1月前
|
机器学习/深度学习 算法 机器人
使用哈里斯角Harris和SIFT算法来实现局部特征匹配(Matlab代码实现)
使用哈里斯角Harris和SIFT算法来实现局部特征匹配(Matlab代码实现)
137 8

热门文章

最新文章