-贪婪策略
-贪婪策略
-贪婪策略)被提出,其基本思想就是使得某一状态下所有可能的行为都有几率被选中执行,具体通过设置一个比较小的
值,使用
的概率贪婪地选择目前认为是最大行为价值的行为,而用
的概率随机从所有m个可选行为中选择行为,即:
-贪婪策略采样一个或多个完整的状态序列后,平均得出某一状态行为对的价值,并持续进行策略评估和改善(通过状态行为对的价值Q).如下图所示:
-贪婪策略进行现时蒙特卡洛控制仍然只能得到基于该策略的近似行为价值函数,这是因为该策略一直在进行探索,而没有一个终止条件.因此我们必须关注以下两个方面:一方面我们不想丢掉任何更好信息和状态,另一方面随着我们策略的改善我们最终希望能终止于某一个最优策略.为此引入了另一个理论概念GLIE(greedy in the Limit with Infinite Exploration).它包含两层意思,一是所有的状态行为对会被无限次探索:
-贪婪策略时,能令
随采样次数的无限增加而趋向于0就符合GLIE.这样基于GLIE的蒙特卡洛控制流程如下:
,采样第
个完整的状态序列:{
}
,更新其计数N和行为价值函数Q:
的取值可不局限于取
,只要符合GLIE特性的设计均可以收敛至最优策略(价值)
)算法
-贪婪策略进行策略迭代:
是学习速率参数,
是衰减因子.当行为策略满足前文所述GLIE特性同时学习率参数
满足:
算法
对应的是一个状态行为对
,表示的是在某个状态下采取某个行为的价值大小.如果n=1,则表示状态行为对
的Q价值可以用两部分表示,一部分是离开状态
得到的即时奖励,
,即时奖励只与状态有关,与该状态下采取的行为无关;另一部分是考虑了衰减因子的状态行为对
的价值:环境给了个体一个后续状态
,观察在该状态基于当前策略得到的行为
时的价值
.当n=2时,就用前2步的即时奖励,然后再用后续的
代替;如果n趋向于无穷大,则表示一直用带衰减因子的即时奖励计算Q值,直至状态序列结束.
),可以给n-步Q收获中的每一步收获分配一个权重,并按权重对每一步Q收获求和,那么将得到
收获,它结合了所有n-步Q收获:
收获来更新状态行为对的Q值,那么可以表示成如下的形式:
的前向认识,使用它更新Q价值需要遍历完整的状态序列.与TD(
)类似,我们也可以反向理解Sarsa
.同样引入效用追迹(eligibility traces,ET),不同的是这次的E值不是针对一个状态,而是一个状态行为对:
)算法中对Q值更新的描述:
),基于反向认识的Sarsa(
)算法将可以有效地在线学习,数据学习完即可丢弃(因为不需要学习完整的Episode).
)的算法流程如算法2描述:
是在每浏览完一个Episode后需要重新置0,这体现了ET仅在一个Episode中发挥作用;其次要提及的是算法更新Q和E的时候针对的不是某个Episode里的Q或E,而是针对个体掌握的整个状态空间和行为空间产生的Q和E.
)算法的区别:假设图最左侧描述的路线是个体采取两种算法中的一个得到的一个完整状态序列的路径:
,同时给以即时奖励0,在这个新位置上,根据当前的策略它会产生新位置下的一个行为,个体不执行该行为,仅仅在表中查找新状态下新行为的Q值,由于Q=0,依据更新公式,它将把刚才离开的位置以及对应行为的状态行为对价值Q更新为0.如此直到个体到达终点位置
,它获得一个即时奖励1,此时个体会依据公式更新其到达终点位置前所在的那个位置(暂用
表示,也就是终点位置下方,向上的箭头所在的位置)时采取向上移步的那个状态行为对价值
,它将不再是0,这是个体在这个状态序列中唯一一次用非0数值来更新Q值.这样完成一个状态序列,此时个体已经并只进行了一次有意义的行为价值函数的更新;同时依据新的价值函数产生了新的策略.这个策略绝大多数与之前的相同,只是当个体处在特殊位置
时将会有一个近乎确定的向上的行为.这里请不要误认为Sarsa算法只在经历一个完整的状态序列之后才会更新,在这个例子中,由于我们的设定,它每走一步都会更新,只是多数时候更新的数据与原来的一样罢了.
,在这个位置,个体更新的策略将使其有非常大的几率选择向上的行为直接进入终点位置
.
价值比较大,因为在这个位置直接采取向上移步的行为就可以拿到终点的即时奖励.因此它会将那些通过移动一步就可以到达
位置的其他位置以及相应的到达该位置所要采取的行为对所对应的价值进行提升.如此反复,如果采用贪婪策略更新,个体最终将得到一条到达终点的路径,不过这条路径的倒数第二步永远是在终点位置的下方.如果采用
-贪婪策略更新,那么个体还会尝试到终点位置的左上右等其他方向的相邻位置价值也比较大,此时个体每次完成的路径可能都不一样.通过重复多次搜索,这种Q值的实质有意义的更新将覆盖越来越多的状态行为对,个体在早起采取的随机行为步数将越来越少,直至最终实质性的更新覆盖到起始位置.此时个体将能直接给出一条确定的从起点到终点的路径.
算法:该算法同时还针对每一次状态序列维护一个关于状态行为对
的E表,初始时E表值均为0.当个体首次在起点
决定移动一步
(假设向右)时,它环境告知新位置为
,此时发生如下事情:首先个体会做一个标记,使
的值增加1,表明个体刚刚经历过这个事件
;其次它要估计这个事件对于解决整个问题的价值,也就是估计TD误差,此时依据公式结果为0,说明个体认为在起点处向右走没什么价值,这个"没有什么价值"有两层含义:不仅说明在
处向右走没什么价值,同时表明个体认为所有能够到达
状态的状态行为对的价值没有任何积极或消极的变化.随后个体将要更新该状态序列中所有已经经历的
值,由于存在E值,那些在
之前近期发生或频繁发生的
将改变得比其他Q值明显些,此外个体还要更新其E值,以备下次使用.对于刚从起点出发的个体,这次更新没有使得任何Q值发生变化,仅仅在
处有了一个实质的变化.随后的过程类似,个体有意义的发现就是对路径有了一个记忆,体现在E里,具体的Q值没发生变化.这一情况直到个体到达终点位置时发生改变.此时个体得到了一个即时奖励1,它会发现这一次变化(从
采取向上行为
到达
)价值明显,它会计算这个TD误差为1,同时告诉整个经历过程中所有(S,A),根据其与
的密切关系更新这些状态行为对的价值Q,个体在这个状态序列中经历的所有状态行为对的Q值都将得到一个非0的更新,但是那些在个体到达
之前就近发生以及频繁发生的状态行为对的价值提升会更加明显.
,这时的
的价值也会得到较多提升.也就是说,个体每得到一个即时奖励,同时会对所有历史事件的价值进行依次更新,当然那些与该事件关系紧密的事件价值改变的较为明显.这里的事件指的就是状态行为对.在同一状态采取不同行为是不同的事件.
-贪婪策略更新,那么个体还会尝试新的路线.由于为了解释方便,做了一些约定,这会导致问题并不要求个体找到最短一条路径,如果需要找最短路径,需要在每一次状态转移时给个体一个负的奖励.
)算法在状态每发生一次变化都对整个状态空间和行为空间的Q和E值进行更新,而事实上在每一个状态序列里,只有个体经历过的状态行为对的E值才可能不为0,为什么不仅仅对该状态序列涉及到的状态行为对进行更新呢?理论上是可以仅对该状态序列里设计的状态行为对的E和Q进行更新的,不过这要额外维护一个表,而往这个额外的表里添加新的状态行为对的E和Q值比更新总的状态行为空间要麻烦,特别是在早期个体没有一个较好的策略的时候需要花费很长很长时间才能找到终点位置,这在一定程度上反而没有更新状态空间省时.不过随着学习深入,策略得到优化,此表的规模会变小.
与评价策略
是不同的策略,具体地说,个体通过策略
生成行为与环境发生实际交互,但是在更新这个状态行为对价值时使用的是目标策略
.目标策略
多数是已经具备一定能力的策略,例如人类已有的经验或个其他个体学习到的经验.离线策略学习相当于站在目标策略
的"肩膀"上学习.离线策略学习根据是否经历完整的状态序列可以将其分为基于蒙特卡洛的和基于TD的.基于蒙特卡洛的离线测了学习目前认为仅有理论上的研究价值,在实际中用处不大,这里主要讲解常用的离线策略TD学习.
的基础上更新行为价值,进而优化行为策略:
中,基于行为策略
产生了一个行为
,执行该行为后进入新的状态
,离线策略学习要做的事情就是,比较评价策略和行为策略在状态
下产生同样的行为
的概率的比值,如果这个比值接近1,说明两个策略在状态
下采取行为
的概率差不多,此次对于状态
价值的更新同时得到两个策略的支持.如果这一概率比值很小,则表明评价策略
在状态
下采取行为
的概率差不多,此次对于状态
价值的更新同时得到两个策略的支持.如果这一概率比值很小,则表明评价策略
在状态
下选择
的机会要小一些,此时为了从评价策略学习,我们认为这一步状态价值的更新不是很符合评价策略,因而在更新时打些折扣.类似的,如果这个概率比值大于1,说明按照评价策略,选择行为
的几率要大于当前行为策略产生
的概率,此时应该对该状态的价值更新就可以大胆些.
是基于行为价值函数
-贪婪策略,评价策略
则是基于
的完全贪婪策略,这种学习方法称为Q学习(Q-learning)
,在Q学习的过程中,t时刻的与环境进行交互的行为
由策略
产生:
是一个
-贪婪策略.
时刻用来更新的行为
由下式产生:
是一个完全贪婪策略.
按下式更新:
产生的行为A'得到的Q值.根据这种价值更新的方式,状态
根据
-贪婪策略得到的行为
的价值将朝着
状态下贪婪策略确定的最大行为价值的方向做一定比例的更新.这种算法能够使个体的行为策略
更加接近贪婪策略,同时保证个体能持续探索并经历足够丰富的新状态,并最终收敛至最优策略和最优行为价值函数.
贪婪的,因此都会偶尔发生坠入悬崖的情况,如果
贪婪策略中的
随着经历的增加而趋向于0,则两种算法都将最后收敛至最优策略.
from blackjack import Player, Dealer, Arena
from utils import str_key,set_dict,get_dict
from utils import draw_value, draw_policy
from utils import epsilon_greedy_policy
import math
class MC_Player(Player):
'''
具备蒙特卡洛控制能力的玩家
'''
def __init__(self, name = "", A = None, display = False):
super(MC_Player, self).__init__(name, A, display)
self.Q = {} #某一状态行为对的价值,策略迭代时使用
self.Nsa = {} #Nsa的计数:某一状态行为对出现的次数
self.total_learning_times = 0
self.policy = self.epsilon_greedy_policy
self.lerning_method = self.learn_Q #有了自己的学习方法
def learn_Q(self, episode, r): #从状态序列来学习Q值
'''
从一个episode学习
:param episode:
:param r:reward
:return:None
'''
for s, a in episode:
nsa = get_dict(self.Nsa, s, a)
set_dict(self.Nsa, nsa+1, s, a)
q = get_dict(self.Q, s, a)
set_dict(self.Q, q+(r-q)/(nsa+1), s, a)
self.total_learning_times += 1
def reset_memory(self):
'''
忘记既往学习经历
:return:None
'''
self.Q.clear()
self.Nsa.clear()
self.total_learning_times = 0
def epsilon_greedy_policy(self, dealer, epsilon = None):
'''
这里的贪婪策略是带有epsilon参数的
:param dealer:庄家
:param epsilon:贪婪率
:return:根据epsilon-greedy选出的策略
'''
player_points, _ = self.get_points()
if player_points >= 21:
return self.A[1]
if player_points < 12:
return self.A[0]
else:
A, Q = self.A, self.Q
s = self.get_state_name(dealer)
if epsilon is None:
epsilon = 1.0/(1 + 4 * math.log10(1+player.total_learning_times))
return epsilon_greedy_policy(A, s, Q, epsilon)
-贪婪策略.接下来我们使用MC_Player类来生成对局,庄家的策略仍然不变.
A = ["继续叫牌", "停止叫牌"]
display = False
player = MC_Player(A = A, display = display)
dealer = Dealer(A = A, display = display)
arena = Arena(A = A, display = display)
arena.play_games(dealer = dealer, player = player, num = 200000, show_statistic=True)
# 共玩了200000局,玩家赢84463局,和17295局,输98242局,胜率:0.42,不输率:0.51
# 100%|██████████| 200000/200000 [00:24<00:00, 8135.69it/s]
draw_value(player.Q, useable_ace = True, is_q_dict=True, A = player.A)
draw_policy(epsilon_greedy_policy, player.A, player.Q, epsilon = 1e-10, useable_ace = True)
draw_value(player.Q, useable_ace = False, is_q_dict=True, A = player.A)
draw_policy(epsilon_greedy_policy, player.A, player.Q, epsilon = 1e-10, useable_ace = False)
)、采取的行为 (
)、上一个行为得到的奖励
这三个方面。描述一个完整的状态转换还应包括这两个信息:下一时刻个体的状态 (
) 和下一时刻的状态是否是终止状态 (is_end).
class State(object):
def __init__(self, name):
self.name = name
class Transition(object):
def __init__(self, s0, a0, reward: float, is_done: bool, s1):
self.data = [s0, a0, reward, is_done, s1]
def __iter__(self):
return iter(self.data)
def __str__(self):
return "s:{0:<3} a:{1:<3} r:{2:<4} is_end:{3:<5} s1:{4:<3}". \
format(self.data[0], self.data[1], self.data[2], \
self.data[3], self.data[4])
@property
def s0(self): return self.data[0]
@property
def a0(self): return self.data[1]
@property
def reward(self): return self.data[2]
@property
def is_done(self): return self.data[3]
@property
def s1(self): return self.data[4]
class Episode(object):
def __init__(self, e_id: int = 0) -> None:
self.total_reward = 0 # 总的获得的奖励
self.trans_list = [] # 状态转移列表
self.name = str(e_id) # 可以给Episode起个名字:"成功闯关,黯然失败?"
def push(self, trans: Transition) -> float:
self.trans_list.append(trans)
self.total_reward += trans.reward # 不计衰减的总奖励
return self.total_reward
@property
def len(self):
return len(self.trans_list)
def __str__(self):
return "episode {0:<4} {1:>4} steps,total reward:{2:<8.2f}". \
format(self.name, self.len, self.total_reward)
def print_detail(self):
print("detail of ({0}):".format(self))
for i, trans in enumerate(self.trans_list):
print("step{0:<4} ".format(i), end=" ")
print(trans)
def pop(self) -> Transition:
'''normally this method shouldn't be invoked.
'''
if self.len > 1:
trans = self.trans_list.pop()
self.total_reward -= trans.reward
return trans
else:
return None
def is_complete(self) -> bool:
'''check if an episode is an complete episode
'''
if self.len == 0:
return False
return self.trans_list[self.len - 1].is_done
def sample(self, batch_size=1):
'''随即产生一个trans
'''
return random.sample(self.trans_list, k=batch_size)
def __len__(self) -> int:
return self.len
class Experience(object):
'''this class is used to record the whole experience of an agent organized
by an episode list. agent can randomly sample transitions or episodes from
its experience.
'''
def __init__(self, capacity: int = 20000):
self.capacity = capacity # 容量:指的是trans总数量
self.episodes = [] # episode列表
self.next_id = 0 # 下一个episode的Id
self.total_trans = 0 # 总的状态转换数量
def __str__(self):
return "exp info:{0:5} episodes, memory usage {1}/{2}". \
format(self.len, self.total_trans, self.capacity)
def __len__(self):
return self.len
@property
def len(self):
return len(self.episodes)
def _remove(self, index=0):
'''扔掉一个Episode,默认第一个。
remove an episode, defautly the first one.
args:
the index of the episode to remove
return:
if exists return the episode else return None
'''
if index > self.len - 1:
raise (Exception("invalid index"))
if self.len > 0:
episode = self.episodes[index]
self.episodes.remove(episode)
self.total_trans -= episode.len
return episode
else:
return None
def _remove_first(self):
self._remove(index=0)
def push(self, trans):
'''压入一个状态转换
'''
if self.capacity <= 0:
return
while self.total_trans >= self.capacity: # 可能会有空episode吗?
episode = self._remove_first()
cur_episode = None
if self.len == 0 or self.episodes[self.len - 1].is_complete():
cur_episode = Episode(self.next_id)
self.next_id += 1
self.episodes.append(cur_episode)
else:
cur_episode = self.episodes[self.len - 1]
self.total_trans += 1
return cur_episode.push(trans) # return total reward of an episode
def sample(self, batch_size=1): # sample transition
'''randomly sample some transitions from agent's experience.abs
随机获取一定数量的状态转化对象Transition
args:
number of transitions need to be sampled
return:
list of Transition.
'''
sample_trans = []
for _ in range(batch_size):
index = int(random.random() * self.len)
sample_trans += self.episodes[index].sample()
return sample_trans
def sample_episode(self, episode_num=1): # sample episode
'''随机获取一定数量完整的Episode
'''
return random.sample(self.episodes, k=episode_num)
@property
def last_episode(self):
if self.len > 0:
return self.episodes[self.len - 1]
return None
class Agent(object):
'''Base Class of Agent
'''
def __init__(self, env: Env = None,
capacity=10000):
# 保存一些Agent可以观测到的环境信息以及已经学到的经验
self.env = env # 建立对环境对象的引用
self.obs_space = env.observation_space if env is not None else None
self.action_space = env.action_space if env is not None else None
self.S = [i for i in range(self.obs_space.n)]
self.A = [i for i in range(self.action_space.n)]
self.experience = Experience(capacity=capacity)
# 有一个变量记录agent当前的state相对来说还是比较方便的。要注意对该变量的维护、更新
self.state = None # 个体的当前状态
def policy(self, A, s=None, Q=None, epsilon=None):
'''均一随机策略
'''
return random.sample(self.A, k=1)[0]
def perform_policy(self, s, Q=None, epsilon=0.05):
action = self.policy(self.A, s, Q, epsilon)
return int(action)
def act(self, a0):
s0 = self.state
s1, r1, is_done, info = self.env.step(a0)
# TODO add extra code here
trans = Transition(s0, a0, r1, is_done, s1)
total_reward = self.experience.push(trans)
self.state = s1
return s1, r1, is_done, info, total_reward
def learning_method(self, lambda_=0.9, gamma=0.9, alpha=0.5, epsilon=0.2, display=False):
'''这是一个没有学习能力的学习方法
具体针对某算法的学习方法,返回值需是一个二维元组:(一个状态序列的时间步、该状态序列的总奖励)
'''
self.state = self.env.reset()
s0 = self.state
if display:
self.env.render()
a0 = self.perform_policy(s0, epsilon)
time_in_episode, total_reward = 0, 0
is_done = False
while not is_done:
# add code here
s1, r1, is_done, info, total_reward = self.act(a0)
if display:
self.env.render()
a1 = self.perform_policy(s1, epsilon)
# add your extra code here
s0, a0 = s1, a1
time_in_episode += 1
if display:
print(self.experience.last_episode)
return time_in_episode, total_reward
def learning(self, lambda_=0.9, epsilon=None, decaying_epsilon=True, gamma=0.9,
alpha=0.1, max_episode_num=800, display=False):
total_time, episode_reward, num_episode = 0, 0, 0
total_times, episode_rewards, num_episodes = [], [], []
for i in tqdm(range(max_episode_num)):
if epsilon is None:
epsilon = 1e-10
elif decaying_epsilon:
epsilon = 1.0 / (1 + num_episode)
time_in_episode, episode_reward = self.learning_method(lambda_=lambda_, \
gamma=gamma, alpha=alpha, epsilon=epsilon,
display=display)
total_time += time_in_episode
num_episode += 1
total_times.append(total_time)
episode_rewards.append(episode_reward)
num_episodes.append(num_episode)
# self.experience.last_episode.print_detail()
return total_times, episode_rewards, num_episodes
def sample(self, batch_size=64):
'''随机取样
'''
return self.experience.sample(batch_size)
@property
def total_trans(self):
'''得到Experience里记录的总的状态转换数量
'''
return self.experience.total_trans
def last_episode_detail(self):
self.experience.last_episode.print_detail()
import gym
from gym import Env
from gridworld import WindyGridWorld#导入有风格子世界环境
from core import Agent#导入个体基类
import time
env = WindyGridWorld()#生成有风格子世界环境对象
env.reset()#重置环境对象
env.render()#显示环境对象可视化界面
agent = Agent(env, capacity=10000)#创建Agent对象
data = agent.learning(max_episode_num=180, display=True)
time.sleep(10)
env.close()
)和Q学习能力的三个个体子类,我们只要分别实现其策略方法以及学习方法就可以了.
from random import random,choice
from core import Agent
from gym import Env
import gym
from gridworld import WindyGridWorld,SimpleGridWorld
from utils import str_key,set_dict,get_dict
from utils import epsilon_greedy_policy,epsilon_greedy_pi
from utils import greedy_policy,learning_curve
class SarsaAgent(Agent):
def __init__(self, env:Env, capacity:int = 20000):
super(SarsaAgent, self).__init__(env,capacity)
self.Q = {}#增加Q字典存储行为价值
def policy(self, A, s=None, Q=None, epsilon=None):
'''
使用epsilon-贪婪策略
'''
return epsilon_greedy_policy(A, s, Q, epsilon)
def learning_method(self, gamma =0.9, alpha=0.1, epsilon=1e-5, display=False, lambda_ = None):
self.state = self.env.reset()
s0 = self.state
if display:
self.env.render()
a0 = self.perform_policy(s0, self.Q, epsilon)
time_in_episode, total_reward = 0, 0
is_done = False
while not is_done:
s1, r1, is_done, info, total_reward = self.act(a0)
if display:
self.env.render()
a1 = self.perform_policy(s1, self.Q, epsilon)
old_q = get_dict(self.Q, s0, a0)
q_prime = get_dict(self.Q, s1, a1)
td_target = r1 + gamma * q_prime
new_q = old_q + alpha * (td_target - old_q)
set_dict(self.Q, new_q, s0, a0)
s0, a0 = s1, a1
time_in_episode += 1
if display:
print(self.experience.last_episode)
return time_in_episode, total_reward
)
class SarsaLambdaAgent(Agent):
def __init__(self, env:Env, capacity:int = 20000):
super(SarsaLambdaAgent,self).__init__(env,capacity)
self.Q = {}
def policy(self, A, s=None, Q=None, epsilon=None):
return epsilon_greedy_policy(A, s, Q, epsilon)
def learning_method(self, lambda_=0.9, gamma=0.9, alpha=0.1, epsilon=1e-5, display=False):
self.state = self.env.reset()
s0 = self.state
if display:
self.env.reset()
a0 = self.perform_policy(s0, self.Q, epsilon)
time_in_episode, total_reward = 0,0
is_done = False
E = {}#效用值
while not is_done:
s1, r1, is_done, info, total_reward = self.act(a0)
if display:
self.env.render()
a1 = self.perform_policy(s1, self.Q, epsilon)
q = get_dict(self.Q, s0, a0)
q_prime = get_dict(self.Q, s1, a1)
delta = r1 + gamma * q_prime -q
e = get_dict(E, s0, a0)
e+= 1
set_dict(E, e, s0, a0)
for s in self.S:#对所有可能的Q(s,a)进行更新
for a in self.A:
e_value = get_dict(E, s, a)
old_q = get_dict(self.Q, s, a)
new_q = old_q + alpha * delta * e_value
new_e = gamma * lambda_ * e_value
set_dict(self.Q, new_q, s, a)
set_dict(E, new_e, s, a)
s0, a0 = s1, a1
time_in_episode += 1
if display:
print(self.experience.last_episode)
return time_in_episode,total_reward
class QAgent(Agent):
def __init__(self, env:Env, capacity:int = 20000):
super(QAgent, self).__init__(env, capacity)
self.Q = {}
def policy(self, A, s=None, Q=None, epsilon=None):
return epsilon_greedy_policy(A, s, Q, epsilon)
def learning_method(self,gamma=0.9, alpha=0.1, epsilon=1e-5, display=False, lambda_ = None):
self.state = self.env.reset()
s0 = self.state
if display:
self.env.render()
time_in_episode, total_reward = 0,0
is_done = False
while not is_done:
self.policy = epsilon_greedy_policy#行为策略
a0 = self.perform_policy(s0, self.Q, epsilon)
s1, r1, is_done, info, total_reward = self.act(a0)
if display:
self.env.render()
self.policy = greedy_policy
a1 = greedy_policy(self.A, s1, self.Q)#借鉴策略
old_q = get_dict(self.Q, s0, a0)
q_prime = get_dict(self.Q, s1, a1)
td_target = r1 + gamma * q_prime
new_q = old_q + alpha * (td_target - old_q)
set_dict(self.Q, new_q, s0, a0)
s0 = s1
time_in_episode += 1
if display:
print(self.experience.last_episode)
return time_in_episode,total_reward
env = WindyGridWorld()
agent = SarsaLambdaAgent(env, capacity = 10000)
statistics = agent.learning(gamma = 1.0,
epsilon = 1,
decaying_epsilon = True,
alpha = 0.5,
max_episode_num = 800,
display = False)
agent.learning_method(epsilon = 0.01, display = True)