在下面的代码中,这是通过Q学习求解FrozenLake 4x4的代码。在训练部分,为什么我们要在测试环境中播放20集,而不是每个循环中只播放1集?我尝试了两次迭代:
当运行测试环境的20次迭代时,代理在16000多次尝试中收敛。
当进行测试环境的1次迭代时,代理在不到1000次尝试中收敛。
import gym
import collections
from tensorboardX import SummaryWriter
ENV_NAME = "FrozenLake-v0"
GAMMA = 0.9
ALPHA = 0.2
TEST_EPISODES = 20
class Agent:
def __init__(self):
self.env = gym.make(ENV_NAME)
self.state = self.env.reset()
self.values = collections.defaultdict(float)
def sample_env(self):
action = self.env.action_space.sample()
old_state = self.state
new_state, reward, is_done, _ = self.env.step(action)
self.state = self.env.reset() if is_done else new_state
return (old_state, action, reward, new_state)
def best_value_and_action(self, state):
best_value, best_action = None, None
for action in range(self.env.action_space.n):
action_value = self.values[(state, action)]
if best_value is None or best_value < action_value:
best_value = action_value
best_action = action
return best_value, best_action
def value_update(self, s, a, r, next_s):
best_v, _ = self.best_value_and_action(next_s)
new_val = r + GAMMA * best_v
old_val = self.values[(s, a)]
self.values[(s, a)] = old_val * (1-ALPHA) + new_val * ALPHA
def play_episode(self, env):
total_reward = 0.0
state = env.reset()
while True:
_, action = self.best_value_and_action(state)
new_state, reward, is_done, _ = env.step(action)
total_reward += reward
if is_done:
break
state = new_state
return total_reward
if __name__ == "__main__":
test_env = gym.make(ENV_NAME)
agent = Agent()
writer = SummaryWriter(comment="-q-learning")
iter_no = 0
best_reward = 0.0
while True:
iter_no += 1
s, a, r, next_s = agent.sample_env()
agent.value_update(s, a, r, next_s)
reward = 0.0
for _ in range(TEST_EPISODES):
reward += agent.play_episode(test_env)
reward /= TEST_EPISODES
writer.add_scalar("reward", reward, iter_no)
if reward > best_reward:
print("Best reward updated %.3f -> %.3f" % (best_reward, reward))
best_reward = reward
if reward > 0.80:
print("Solved in %d iterations!" % iter_no)
break
writer.close()发布于 2019-01-18 10:13:24
在本例中,TEST_EPISODES用于更改求解条件。对于TEST_EPISODES = 1,只要最近一次游戏的分数达到> 0.80,就认为游戏已经解决;使用TEST_EPISODES = 20,最近20轮的平均分数必须大于0.80,才能认为游戏已经解决。
由于这个游戏具有随机动作,即每次在相同状态下采取相同动作不会得到相同的结果,因此TEST_EPISODES越高,解决方案可能越稳健。对于TEST_EPISODES = 1,如果第一次尝试时碰巧随机找到目标,这个脚本就会认为游戏已经解决了,但是在一个糟糕的模型中连续20次这样做的可能性要小得多。
对于这些类型的问题,较大剧集数量的平均值通常是比第一次达到目标的速度更好的度量标准。想象一下,如果你不得不在这种环境中操作,而你的生活依赖于安全地达到目标,你可能会希望它学习,直到分数阈值更接近于1。
https://stackoverflow.com/questions/54211235
复制相似问题