如上图所示为online/offline_forward/backward_TD(λ)与MC之间的关系,本文将四种算法统一在同一个类下,对比其代码实现的细节。
import numpy as np
from tqdm import tqdm
import matplotlib
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 正确显示中文
plt.rcParams['axes.unicode_minus'] = False # 正确显示正负号
from TD1 import *
N_STATES = 19 # 共有19个状态
GAMMA = 1 # 折扣系数
STATES = np.arange(1, N_STATES + 1) # 状态合计【1,2,3,4,……,19】
START_STATE = int((N_STATES + 1) / 2) # 起始状态_中间位置开始
# S=0时,左边终止 reward=-1
# S=20时,右边终止 reward=1
END_STATES = [0, N_STATES + 1]
# 随机游走问题中真实的价值函数,用来通过误差评比各种算法的预测能力
TRUE_VALUE = np.arange(-20, 22, 2) / 20.0
TRUE_VALUE[0] = TRUE_VALUE[-1] = 0 # 第一个和最后一个都是0
父类属性设置
class ValueFunction:
def __init__(self, step_size): # 每个算法都需要的共同属性(继承)
self.step_size = step_size # 更新步长alpha
self.weights = np.zeros(N_STATES + 2) # 储存每个状态对应的价值
# 传入价值
def value(self, state):
return self.weights[state]
# 传入新的观测值[state, reward]
# 各子类需重写此函数(学习策略)
def learn(self, state, reward):
return
# 在新的episode开始时刻进行初始化
# 需要重新
def new_episode(self):
return
1、Online_n_step_TD
同上篇博客的n步TD算法,其更新原理如下图。
class Online_n_step_TD(ValueFunction): # 由父类继承
def __init__(self, n, step_size):
ValueFunction.__init__(self, step_size) # 继承父类的属性
self.n = n
def new_episode(self): # episode从哪开始
self.trajectory = [START_STATE]
self.rewards = [0.0]
self.time = 0
self.T = float('inf')
def n_step_return_from_time(self, time): # 得到time时刻的n步累计回报
end_time = min(time + self.n , self.T)
returns = 0.0
for t in range(time + 1, end_time + 1): # 计算累计收益
returns += pow(GAMMA, t - time - 1) * self.rewards[t]
if time + self.n