mirror of
https://github.com/wassname/ray.git
synced 2026-07-17 11:32:33 +08:00
* make information available for GAE * buggy version of GAE estimator * fix * add more logging and reweight losses * fix logging * fix loss * adapt advantage calculation * update gae * standardize returns * don't normalize td lambda ret * fix * don't standardize advantages * do standardization earlier * different standardization * initializer * drop into the debugger * fix tensorflow broadcasting bug * vf clipping * don't standardize tdlambdaret * different standardization * use huber loss for value function * refactor -- first half * it runs * fix * update * documentation * linting and tests * fix linting * naming * fix * linting * fix * remove prefix madness * fixes * fix * add value function example * fix linting * remove newline
132 lines
5.1 KiB
Python
132 lines
5.1 KiB
Python
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import print_function
|
|
|
|
import numpy as np
|
|
import ray
|
|
|
|
from ray.rllib.policy_gradient.filter import NoFilter
|
|
from ray.rllib.policy_gradient.utils import concatenate
|
|
|
|
|
|
def rollouts(policy, env, horizon, observation_filter=NoFilter(),
|
|
reward_filter=NoFilter()):
|
|
"""Perform a batch of rollouts of a policy in an environment.
|
|
|
|
Args:
|
|
policy: The policy that will be rollout out. Can be an arbitrary object
|
|
that supports a compute_actions(observation) function.
|
|
env: The environment the rollout is computed in. Needs to support the
|
|
OpenAI gym API and needs to support batches of data.
|
|
horizon: Upper bound for the number of timesteps for each rollout in
|
|
the batch.
|
|
observation_filter: Function that is applied to each of the
|
|
observations.
|
|
reward_filter: Function that is applied to each of the rewards.
|
|
|
|
Returns:
|
|
A trajectory, which is a dictionary with keys "observations",
|
|
"rewards", "orig_rewards", "actions", "logprobs", "dones". Each
|
|
value is an array of shape (num_timesteps, env.batchsize, shape).
|
|
"""
|
|
|
|
observation = observation_filter(env.reset())
|
|
done = np.array(env.batchsize * [False])
|
|
t = 0
|
|
observations = [] # Filtered observations
|
|
raw_rewards = [] # Empirical rewards
|
|
actions = [] # Actions sampled by the policy
|
|
logprobs = [] # Last layer of the policy network
|
|
vf_preds = [] # Value function predictions
|
|
dones = [] # Has this rollout terminated?
|
|
|
|
while True:
|
|
action, logprob, vfpred = policy.compute(observation)
|
|
vf_preds.append(vfpred)
|
|
observations.append(observation[None])
|
|
actions.append(action[None])
|
|
logprobs.append(logprob[None])
|
|
observation, raw_reward, done = env.step(action)
|
|
observation = observation_filter(observation)
|
|
raw_rewards.append(raw_reward[None])
|
|
dones.append(done[None])
|
|
t += 1
|
|
if done.all() or t >= horizon:
|
|
break
|
|
|
|
return {"observations": np.vstack(observations),
|
|
"raw_rewards": np.vstack(raw_rewards),
|
|
"actions": np.vstack(actions),
|
|
"logprobs": np.vstack(logprobs),
|
|
"vf_preds": np.vstack(vf_preds),
|
|
"dones": np.vstack(dones)}
|
|
|
|
|
|
def add_return_values(trajectory, gamma, reward_filter):
|
|
rewards = trajectory["raw_rewards"]
|
|
dones = trajectory["dones"]
|
|
returns = np.zeros_like(rewards)
|
|
last_return = np.zeros(rewards.shape[1], dtype="float32")
|
|
|
|
for t in reversed(range(len(rewards) - 1)):
|
|
last_return = rewards[t, :] * (1 - dones[t, :]) + gamma * last_return
|
|
returns[t, :] = last_return
|
|
reward_filter(returns[t, :])
|
|
|
|
trajectory["returns"] = returns
|
|
|
|
|
|
def add_advantage_values(trajectory, gamma, lam, reward_filter):
|
|
rewards = trajectory["raw_rewards"]
|
|
vf_preds = trajectory["vf_preds"]
|
|
dones = trajectory["dones"]
|
|
advantages = np.zeros_like(rewards)
|
|
last_advantage = np.zeros(rewards.shape[1], dtype="float32")
|
|
|
|
for t in reversed(range(len(rewards) - 1)):
|
|
delta = rewards[t, :] * (1 - dones[t, :]) + \
|
|
gamma * vf_preds[t+1, :] * (1 - dones[t+1, :]) - vf_preds[t, :]
|
|
last_advantage = \
|
|
delta + gamma * lam * last_advantage * (1 - dones[t+1, :])
|
|
advantages[t, :] = last_advantage
|
|
reward_filter(advantages[t, :])
|
|
|
|
trajectory["advantages"] = advantages
|
|
trajectory["td_lambda_returns"] = \
|
|
trajectory["advantages"] + trajectory["vf_preds"]
|
|
|
|
|
|
def collect_samples(agents,
|
|
config,
|
|
observation_filter=NoFilter(),
|
|
reward_filter=NoFilter()):
|
|
num_timesteps_so_far = 0
|
|
trajectories = []
|
|
total_rewards = []
|
|
trajectory_lengths = []
|
|
# This variable maps the object IDs of trajectories that are currently
|
|
# computed to the agent that they are computed on; we start some initial
|
|
# tasks here.
|
|
agent_dict = {agent.compute_steps.remote(
|
|
config["gamma"], config["lambda"],
|
|
config["horizon"], config["min_steps_per_task"]):
|
|
agent for agent in agents}
|
|
while num_timesteps_so_far < config["timesteps_per_batch"]:
|
|
# TODO(pcm): Make wait support arbitrary iterators and remove the
|
|
# conversion to list here.
|
|
[next_trajectory], waiting_trajectories = ray.wait(
|
|
list(agent_dict.keys()))
|
|
agent = agent_dict.pop(next_trajectory)
|
|
# Start task with next trajectory and record it in the dictionary.
|
|
agent_dict[agent.compute_steps.remote(
|
|
config["gamma"], config["lambda"],
|
|
config["horizon"], config["min_steps_per_task"])] = (
|
|
agent)
|
|
trajectory, rewards, lengths = ray.get(next_trajectory)
|
|
total_rewards.extend(rewards)
|
|
trajectory_lengths.extend(lengths)
|
|
num_timesteps_so_far += len(trajectory["dones"])
|
|
trajectories.append(trajectory)
|
|
return (concatenate(trajectories), np.mean(total_rewards),
|
|
np.mean(trajectory_lengths))
|