sdpkjc commited on
Commit
62da294
1 Parent(s): a2c4ef0

pushing model

Browse files
.gitattributes CHANGED
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ videos/HalfCheetah-v4__ppo_continuous_action__1__1697391142-eval/rl-video-episode-0.mp4 filter=lfs diff=lfs merge=lfs -text
37
+ videos/HalfCheetah-v4__ppo_continuous_action__1__1697391142-eval/rl-video-episode-8.mp4 filter=lfs diff=lfs merge=lfs -text
38
+ videos/HalfCheetah-v4__ppo_continuous_action__1__1697391142-eval/rl-video-episode-1.mp4 filter=lfs diff=lfs merge=lfs -text
39
+ replay.mp4 filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ tags:
3
+ - HalfCheetah-v4
4
+ - deep-reinforcement-learning
5
+ - reinforcement-learning
6
+ - custom-implementation
7
+ library_name: cleanrl
8
+ model-index:
9
+ - name: PPO
10
+ results:
11
+ - task:
12
+ type: reinforcement-learning
13
+ name: reinforcement-learning
14
+ dataset:
15
+ name: HalfCheetah-v4
16
+ type: HalfCheetah-v4
17
+ metrics:
18
+ - type: mean_reward
19
+ value: 2098.44 +/- 1075.59
20
+ name: mean_reward
21
+ verified: false
22
+ ---
23
+
24
+ # (CleanRL) **PPO** Agent Playing **HalfCheetah-v4**
25
+
26
+ This is a trained model of a PPO agent playing HalfCheetah-v4.
27
+ The model was trained by using [CleanRL](https://github.com/vwxyzjn/cleanrl) and the most up-to-date training code can be
28
+ found [here](https://github.com/vwxyzjn/cleanrl/blob/master/cleanrl/ppo_continuous_action.py).
29
+
30
+ ## Get Started
31
+
32
+ To use this model, please install the `cleanrl` package with the following command:
33
+
34
+ ```
35
+ pip install "cleanrl[ppo_continuous_action]"
36
+ python -m cleanrl_utils.enjoy --exp-name ppo_continuous_action --env-id HalfCheetah-v4
37
+ ```
38
+
39
+ Please refer to the [documentation](https://docs.cleanrl.dev/get-started/zoo/) for more detail.
40
+
41
+
42
+ ## Command to reproduce the training
43
+
44
+ ```bash
45
+ curl -OL https://huggingface.co/cleanrl/HalfCheetah-v4-ppo_continuous_action-seed1/raw/main/ppo_continuous_action.py
46
+ curl -OL https://huggingface.co/cleanrl/HalfCheetah-v4-ppo_continuous_action-seed1/raw/main/pyproject.toml
47
+ curl -OL https://huggingface.co/cleanrl/HalfCheetah-v4-ppo_continuous_action-seed1/raw/main/poetry.lock
48
+ poetry install --all-extras
49
+ python ppo_continuous_action.py --track --save-model --upload-model --hf-entity cleanrl --env-id HalfCheetah-v4 --seed 1
50
+ ```
51
+
52
+ # Hyperparameters
53
+ ```python
54
+ {'anneal_lr': True,
55
+ 'batch_size': 2048,
56
+ 'capture_video': False,
57
+ 'clip_coef': 0.2,
58
+ 'clip_vloss': True,
59
+ 'cuda': True,
60
+ 'ent_coef': 0.0,
61
+ 'env_id': 'HalfCheetah-v4',
62
+ 'exp_name': 'ppo_continuous_action',
63
+ 'gae_lambda': 0.95,
64
+ 'gamma': 0.99,
65
+ 'hf_entity': 'cleanrl',
66
+ 'learning_rate': 0.0003,
67
+ 'max_grad_norm': 0.5,
68
+ 'minibatch_size': 64,
69
+ 'norm_adv': True,
70
+ 'num_envs': 1,
71
+ 'num_minibatches': 32,
72
+ 'num_steps': 2048,
73
+ 'save_model': True,
74
+ 'seed': 1,
75
+ 'target_kl': None,
76
+ 'torch_deterministic': True,
77
+ 'total_timesteps': 1000000,
78
+ 'track': True,
79
+ 'update_epochs': 10,
80
+ 'upload_model': True,
81
+ 'vf_coef': 0.5,
82
+ 'wandb_entity': None,
83
+ 'wandb_project_name': 'cleanRL'}
84
+ ```
85
+
events.out.tfevents.1697391154.3090-172.815997.0 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2cd0dc10c6e576f6b3bf453dcc82448b634b3298ee2b59e62d104214a88882fb
3
+ size 376391
poetry.lock ADDED
The diff for this file is too large to render. See raw diff
 
ppo_continuous_action.cleanrl_model ADDED
Binary file (48.9 kB). View file
 
ppo_continuous_action.py ADDED
@@ -0,0 +1,355 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # docs and experiment results can be found at https://docs.cleanrl.dev/rl-algorithms/ppo/#ppo_continuous_actionpy
2
+ import argparse
3
+ import os
4
+ import random
5
+ import time
6
+ from distutils.util import strtobool
7
+
8
+ import gymnasium as gym
9
+ import numpy as np
10
+ import torch
11
+ import torch.nn as nn
12
+ import torch.optim as optim
13
+ from torch.distributions.normal import Normal
14
+ from torch.utils.tensorboard import SummaryWriter
15
+
16
+
17
+ def parse_args():
18
+ # fmt: off
19
+ parser = argparse.ArgumentParser()
20
+ parser.add_argument("--exp-name", type=str, default=os.path.basename(__file__).rstrip(".py"),
21
+ help="the name of this experiment")
22
+ parser.add_argument("--seed", type=int, default=1,
23
+ help="seed of the experiment")
24
+ parser.add_argument("--torch-deterministic", type=lambda x: bool(strtobool(x)), default=True, nargs="?", const=True,
25
+ help="if toggled, `torch.backends.cudnn.deterministic=False`")
26
+ parser.add_argument("--cuda", type=lambda x: bool(strtobool(x)), default=True, nargs="?", const=True,
27
+ help="if toggled, cuda will be enabled by default")
28
+ parser.add_argument("--track", type=lambda x: bool(strtobool(x)), default=False, nargs="?", const=True,
29
+ help="if toggled, this experiment will be tracked with Weights and Biases")
30
+ parser.add_argument("--wandb-project-name", type=str, default="cleanRL",
31
+ help="the wandb's project name")
32
+ parser.add_argument("--wandb-entity", type=str, default=None,
33
+ help="the entity (team) of wandb's project")
34
+ parser.add_argument("--capture-video", type=lambda x: bool(strtobool(x)), default=False, nargs="?", const=True,
35
+ help="whether to capture videos of the agent performances (check out `videos` folder)")
36
+ parser.add_argument("--save-model", type=lambda x: bool(strtobool(x)), default=False, nargs="?", const=True,
37
+ help="whether to save model into the `runs/{run_name}` folder")
38
+ parser.add_argument("--upload-model", type=lambda x: bool(strtobool(x)), default=False, nargs="?", const=True,
39
+ help="whether to upload the saved model to huggingface")
40
+ parser.add_argument("--hf-entity", type=str, default="",
41
+ help="the user or org name of the model repository from the Hugging Face Hub")
42
+
43
+ # Algorithm specific arguments
44
+ parser.add_argument("--env-id", type=str, default="HalfCheetah-v4",
45
+ help="the id of the environment")
46
+ parser.add_argument("--total-timesteps", type=int, default=1000000,
47
+ help="total timesteps of the experiments")
48
+ parser.add_argument("--learning-rate", type=float, default=3e-4,
49
+ help="the learning rate of the optimizer")
50
+ parser.add_argument("--num-envs", type=int, default=1,
51
+ help="the number of parallel game environments")
52
+ parser.add_argument("--num-steps", type=int, default=2048,
53
+ help="the number of steps to run in each environment per policy rollout")
54
+ parser.add_argument("--anneal-lr", type=lambda x: bool(strtobool(x)), default=True, nargs="?", const=True,
55
+ help="Toggle learning rate annealing for policy and value networks")
56
+ parser.add_argument("--gamma", type=float, default=0.99,
57
+ help="the discount factor gamma")
58
+ parser.add_argument("--gae-lambda", type=float, default=0.95,
59
+ help="the lambda for the general advantage estimation")
60
+ parser.add_argument("--num-minibatches", type=int, default=32,
61
+ help="the number of mini-batches")
62
+ parser.add_argument("--update-epochs", type=int, default=10,
63
+ help="the K epochs to update the policy")
64
+ parser.add_argument("--norm-adv", type=lambda x: bool(strtobool(x)), default=True, nargs="?", const=True,
65
+ help="Toggles advantages normalization")
66
+ parser.add_argument("--clip-coef", type=float, default=0.2,
67
+ help="the surrogate clipping coefficient")
68
+ parser.add_argument("--clip-vloss", type=lambda x: bool(strtobool(x)), default=True, nargs="?", const=True,
69
+ help="Toggles whether or not to use a clipped loss for the value function, as per the paper.")
70
+ parser.add_argument("--ent-coef", type=float, default=0.0,
71
+ help="coefficient of the entropy")
72
+ parser.add_argument("--vf-coef", type=float, default=0.5,
73
+ help="coefficient of the value function")
74
+ parser.add_argument("--max-grad-norm", type=float, default=0.5,
75
+ help="the maximum norm for the gradient clipping")
76
+ parser.add_argument("--target-kl", type=float, default=None,
77
+ help="the target KL divergence threshold")
78
+ args = parser.parse_args()
79
+ args.batch_size = int(args.num_envs * args.num_steps)
80
+ args.minibatch_size = int(args.batch_size // args.num_minibatches)
81
+ # fmt: on
82
+ return args
83
+
84
+
85
+ def make_env(env_id, idx, capture_video, run_name, gamma):
86
+ def thunk():
87
+ if capture_video and idx == 0:
88
+ env = gym.make(env_id, render_mode="rgb_array")
89
+ env = gym.wrappers.RecordVideo(env, f"videos/{run_name}")
90
+ else:
91
+ env = gym.make(env_id)
92
+ env = gym.wrappers.FlattenObservation(env) # deal with dm_control's Dict observation space
93
+ env = gym.wrappers.RecordEpisodeStatistics(env)
94
+ env = gym.wrappers.ClipAction(env)
95
+ env = gym.wrappers.NormalizeObservation(env)
96
+ env = gym.wrappers.TransformObservation(env, lambda obs: np.clip(obs, -10, 10))
97
+ env = gym.wrappers.NormalizeReward(env, gamma=gamma)
98
+ env = gym.wrappers.TransformReward(env, lambda reward: np.clip(reward, -10, 10))
99
+ return env
100
+
101
+ return thunk
102
+
103
+
104
+ def layer_init(layer, std=np.sqrt(2), bias_const=0.0):
105
+ torch.nn.init.orthogonal_(layer.weight, std)
106
+ torch.nn.init.constant_(layer.bias, bias_const)
107
+ return layer
108
+
109
+
110
+ class Agent(nn.Module):
111
+ def __init__(self, envs):
112
+ super().__init__()
113
+ self.critic = nn.Sequential(
114
+ layer_init(nn.Linear(np.array(envs.single_observation_space.shape).prod(), 64)),
115
+ nn.Tanh(),
116
+ layer_init(nn.Linear(64, 64)),
117
+ nn.Tanh(),
118
+ layer_init(nn.Linear(64, 1), std=1.0),
119
+ )
120
+ self.actor_mean = nn.Sequential(
121
+ layer_init(nn.Linear(np.array(envs.single_observation_space.shape).prod(), 64)),
122
+ nn.Tanh(),
123
+ layer_init(nn.Linear(64, 64)),
124
+ nn.Tanh(),
125
+ layer_init(nn.Linear(64, np.prod(envs.single_action_space.shape)), std=0.01),
126
+ )
127
+ self.actor_logstd = nn.Parameter(torch.zeros(1, np.prod(envs.single_action_space.shape)))
128
+
129
+ def get_value(self, x):
130
+ return self.critic(x)
131
+
132
+ def get_action_and_value(self, x, action=None):
133
+ action_mean = self.actor_mean(x)
134
+ action_logstd = self.actor_logstd.expand_as(action_mean)
135
+ action_std = torch.exp(action_logstd)
136
+ probs = Normal(action_mean, action_std)
137
+ if action is None:
138
+ action = probs.sample()
139
+ return action, probs.log_prob(action).sum(1), probs.entropy().sum(1), self.critic(x)
140
+
141
+
142
+ if __name__ == "__main__":
143
+ args = parse_args()
144
+ run_name = f"{args.env_id}__{args.exp_name}__{args.seed}__{int(time.time())}"
145
+ if args.track:
146
+ import wandb
147
+
148
+ wandb.init(
149
+ project=args.wandb_project_name,
150
+ entity=args.wandb_entity,
151
+ sync_tensorboard=True,
152
+ config=vars(args),
153
+ name=run_name,
154
+ monitor_gym=True,
155
+ save_code=True,
156
+ )
157
+ writer = SummaryWriter(f"runs/{run_name}")
158
+ writer.add_text(
159
+ "hyperparameters",
160
+ "|param|value|\n|-|-|\n%s" % ("\n".join([f"|{key}|{value}|" for key, value in vars(args).items()])),
161
+ )
162
+
163
+ # TRY NOT TO MODIFY: seeding
164
+ random.seed(args.seed)
165
+ np.random.seed(args.seed)
166
+ torch.manual_seed(args.seed)
167
+ torch.backends.cudnn.deterministic = args.torch_deterministic
168
+
169
+ device = torch.device("cuda" if torch.cuda.is_available() and args.cuda else "cpu")
170
+
171
+ # env setup
172
+ envs = gym.vector.SyncVectorEnv(
173
+ [make_env(args.env_id, i, args.capture_video, run_name, args.gamma) for i in range(args.num_envs)]
174
+ )
175
+ assert isinstance(envs.single_action_space, gym.spaces.Box), "only continuous action space is supported"
176
+
177
+ agent = Agent(envs).to(device)
178
+ optimizer = optim.Adam(agent.parameters(), lr=args.learning_rate, eps=1e-5)
179
+
180
+ # ALGO Logic: Storage setup
181
+ obs = torch.zeros((args.num_steps, args.num_envs) + envs.single_observation_space.shape).to(device)
182
+ actions = torch.zeros((args.num_steps, args.num_envs) + envs.single_action_space.shape).to(device)
183
+ logprobs = torch.zeros((args.num_steps, args.num_envs)).to(device)
184
+ rewards = torch.zeros((args.num_steps, args.num_envs)).to(device)
185
+ dones = torch.zeros((args.num_steps, args.num_envs)).to(device)
186
+ values = torch.zeros((args.num_steps, args.num_envs)).to(device)
187
+
188
+ # TRY NOT TO MODIFY: start the game
189
+ global_step = 0
190
+ start_time = time.time()
191
+ next_obs, _ = envs.reset(seed=args.seed)
192
+ next_obs = torch.Tensor(next_obs).to(device)
193
+ next_done = torch.zeros(args.num_envs).to(device)
194
+ num_updates = args.total_timesteps // args.batch_size
195
+
196
+ for update in range(1, num_updates + 1):
197
+ # Annealing the rate if instructed to do so.
198
+ if args.anneal_lr:
199
+ frac = 1.0 - (update - 1.0) / num_updates
200
+ lrnow = frac * args.learning_rate
201
+ optimizer.param_groups[0]["lr"] = lrnow
202
+
203
+ for step in range(0, args.num_steps):
204
+ global_step += 1 * args.num_envs
205
+ obs[step] = next_obs
206
+ dones[step] = next_done
207
+
208
+ # ALGO LOGIC: action logic
209
+ with torch.no_grad():
210
+ action, logprob, _, value = agent.get_action_and_value(next_obs)
211
+ values[step] = value.flatten()
212
+ actions[step] = action
213
+ logprobs[step] = logprob
214
+
215
+ # TRY NOT TO MODIFY: execute the game and log data.
216
+ next_obs, reward, terminations, truncations, infos = envs.step(action.cpu().numpy())
217
+ done = np.logical_or(terminations, truncations)
218
+ rewards[step] = torch.tensor(reward).to(device).view(-1)
219
+ next_obs, next_done = torch.Tensor(next_obs).to(device), torch.Tensor(done).to(device)
220
+
221
+ # Only print when at least 1 env is done
222
+ if "final_info" not in infos:
223
+ continue
224
+
225
+ for info in infos["final_info"]:
226
+ # Skip the envs that are not done
227
+ if info is None:
228
+ continue
229
+ print(f"global_step={global_step}, episodic_return={info['episode']['r']}")
230
+ writer.add_scalar("charts/episodic_return", info["episode"]["r"], global_step)
231
+ writer.add_scalar("charts/episodic_length", info["episode"]["l"], global_step)
232
+
233
+ # bootstrap value if not done
234
+ with torch.no_grad():
235
+ next_value = agent.get_value(next_obs).reshape(1, -1)
236
+ advantages = torch.zeros_like(rewards).to(device)
237
+ lastgaelam = 0
238
+ for t in reversed(range(args.num_steps)):
239
+ if t == args.num_steps - 1:
240
+ nextnonterminal = 1.0 - next_done
241
+ nextvalues = next_value
242
+ else:
243
+ nextnonterminal = 1.0 - dones[t + 1]
244
+ nextvalues = values[t + 1]
245
+ delta = rewards[t] + args.gamma * nextvalues * nextnonterminal - values[t]
246
+ advantages[t] = lastgaelam = delta + args.gamma * args.gae_lambda * nextnonterminal * lastgaelam
247
+ returns = advantages + values
248
+
249
+ # flatten the batch
250
+ b_obs = obs.reshape((-1,) + envs.single_observation_space.shape)
251
+ b_logprobs = logprobs.reshape(-1)
252
+ b_actions = actions.reshape((-1,) + envs.single_action_space.shape)
253
+ b_advantages = advantages.reshape(-1)
254
+ b_returns = returns.reshape(-1)
255
+ b_values = values.reshape(-1)
256
+
257
+ # Optimizing the policy and value network
258
+ b_inds = np.arange(args.batch_size)
259
+ clipfracs = []
260
+ for epoch in range(args.update_epochs):
261
+ np.random.shuffle(b_inds)
262
+ for start in range(0, args.batch_size, args.minibatch_size):
263
+ end = start + args.minibatch_size
264
+ mb_inds = b_inds[start:end]
265
+
266
+ _, newlogprob, entropy, newvalue = agent.get_action_and_value(b_obs[mb_inds], b_actions[mb_inds])
267
+ logratio = newlogprob - b_logprobs[mb_inds]
268
+ ratio = logratio.exp()
269
+
270
+ with torch.no_grad():
271
+ # calculate approx_kl http://joschu.net/blog/kl-approx.html
272
+ old_approx_kl = (-logratio).mean()
273
+ approx_kl = ((ratio - 1) - logratio).mean()
274
+ clipfracs += [((ratio - 1.0).abs() > args.clip_coef).float().mean().item()]
275
+
276
+ mb_advantages = b_advantages[mb_inds]
277
+ if args.norm_adv:
278
+ mb_advantages = (mb_advantages - mb_advantages.mean()) / (mb_advantages.std() + 1e-8)
279
+
280
+ # Policy loss
281
+ pg_loss1 = -mb_advantages * ratio
282
+ pg_loss2 = -mb_advantages * torch.clamp(ratio, 1 - args.clip_coef, 1 + args.clip_coef)
283
+ pg_loss = torch.max(pg_loss1, pg_loss2).mean()
284
+
285
+ # Value loss
286
+ newvalue = newvalue.view(-1)
287
+ if args.clip_vloss:
288
+ v_loss_unclipped = (newvalue - b_returns[mb_inds]) ** 2
289
+ v_clipped = b_values[mb_inds] + torch.clamp(
290
+ newvalue - b_values[mb_inds],
291
+ -args.clip_coef,
292
+ args.clip_coef,
293
+ )
294
+ v_loss_clipped = (v_clipped - b_returns[mb_inds]) ** 2
295
+ v_loss_max = torch.max(v_loss_unclipped, v_loss_clipped)
296
+ v_loss = 0.5 * v_loss_max.mean()
297
+ else:
298
+ v_loss = 0.5 * ((newvalue - b_returns[mb_inds]) ** 2).mean()
299
+
300
+ entropy_loss = entropy.mean()
301
+ loss = pg_loss - args.ent_coef * entropy_loss + v_loss * args.vf_coef
302
+
303
+ optimizer.zero_grad()
304
+ loss.backward()
305
+ nn.utils.clip_grad_norm_(agent.parameters(), args.max_grad_norm)
306
+ optimizer.step()
307
+
308
+ if args.target_kl is not None:
309
+ if approx_kl > args.target_kl:
310
+ break
311
+
312
+ y_pred, y_true = b_values.cpu().numpy(), b_returns.cpu().numpy()
313
+ var_y = np.var(y_true)
314
+ explained_var = np.nan if var_y == 0 else 1 - np.var(y_true - y_pred) / var_y
315
+
316
+ # TRY NOT TO MODIFY: record rewards for plotting purposes
317
+ writer.add_scalar("charts/learning_rate", optimizer.param_groups[0]["lr"], global_step)
318
+ writer.add_scalar("losses/value_loss", v_loss.item(), global_step)
319
+ writer.add_scalar("losses/policy_loss", pg_loss.item(), global_step)
320
+ writer.add_scalar("losses/entropy", entropy_loss.item(), global_step)
321
+ writer.add_scalar("losses/old_approx_kl", old_approx_kl.item(), global_step)
322
+ writer.add_scalar("losses/approx_kl", approx_kl.item(), global_step)
323
+ writer.add_scalar("losses/clipfrac", np.mean(clipfracs), global_step)
324
+ writer.add_scalar("losses/explained_variance", explained_var, global_step)
325
+ print("SPS:", int(global_step / (time.time() - start_time)))
326
+ writer.add_scalar("charts/SPS", int(global_step / (time.time() - start_time)), global_step)
327
+
328
+ if args.save_model:
329
+ model_path = f"runs/{run_name}/{args.exp_name}.cleanrl_model"
330
+ torch.save(agent.state_dict(), model_path)
331
+ print(f"model saved to {model_path}")
332
+ from cleanrl_utils.evals.ppo_eval import evaluate
333
+
334
+ episodic_returns = evaluate(
335
+ model_path,
336
+ make_env,
337
+ args.env_id,
338
+ eval_episodes=10,
339
+ run_name=f"{run_name}-eval",
340
+ Model=Agent,
341
+ device=device,
342
+ gamma=args.gamma,
343
+ )
344
+ for idx, episodic_return in enumerate(episodic_returns):
345
+ writer.add_scalar("eval/episodic_return", episodic_return, idx)
346
+
347
+ if args.upload_model:
348
+ from cleanrl_utils.huggingface import push_to_hub
349
+
350
+ repo_name = f"{args.env_id}-{args.exp_name}-seed{args.seed}"
351
+ repo_id = f"{args.hf_entity}/{repo_name}" if args.hf_entity else repo_name
352
+ push_to_hub(args, episodic_returns, repo_id, "PPO", f"runs/{run_name}", f"videos/{run_name}-eval")
353
+
354
+ envs.close()
355
+ writer.close()
pyproject.toml ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [tool.poetry]
2
+ name = "cleanrl"
3
+ version = "1.1.0"
4
+ description = "High-quality single file implementation of Deep Reinforcement Learning algorithms with research-friendly features"
5
+ authors = ["Costa Huang <costa.huang@outlook.com>"]
6
+ packages = [
7
+ { include = "cleanrl" },
8
+ { include = "cleanrl_utils" },
9
+ ]
10
+ keywords = ["reinforcement", "machine", "learning", "research"]
11
+ license="MIT"
12
+ readme = "README.md"
13
+
14
+ [tool.poetry.dependencies]
15
+ python = ">=3.7.1,<3.11"
16
+ tensorboard = "^2.10.0"
17
+ wandb = "^0.13.11"
18
+ gym = "0.23.1"
19
+ torch = ">=1.12.1"
20
+ stable-baselines3 = "1.2.0"
21
+ gymnasium = ">=0.28.1"
22
+ moviepy = "^1.0.3"
23
+ pygame = "2.1.0"
24
+ huggingface-hub = "^0.11.1"
25
+ rich = "<12.0"
26
+ tenacity = "^8.2.2"
27
+
28
+ ale-py = {version = "0.7.4", optional = true}
29
+ AutoROM = {extras = ["accept-rom-license"], version = "^0.4.2", optional = true}
30
+ opencv-python = {version = "^4.6.0.66", optional = true}
31
+ procgen = {version = "^0.10.7", optional = true}
32
+ pytest = {version = "^7.1.3", optional = true}
33
+ mujoco = {version = "<=2.3.3", optional = true}
34
+ imageio = {version = "^2.14.1", optional = true}
35
+ free-mujoco-py = {version = "^2.1.6", optional = true}
36
+ mkdocs-material = {version = "^8.4.3", optional = true}
37
+ markdown-include = {version = "^0.7.0", optional = true}
38
+ openrlbenchmark = {version = "^0.1.1b4", optional = true}
39
+ jax = {version = "^0.3.17", optional = true}
40
+ jaxlib = {version = "^0.3.15", optional = true}
41
+ flax = {version = "^0.6.0", optional = true}
42
+ optuna = {version = "^3.0.1", optional = true}
43
+ optuna-dashboard = {version = "^0.7.2", optional = true}
44
+ envpool = {version = "^0.6.4", optional = true}
45
+ PettingZoo = {version = "1.18.1", optional = true}
46
+ SuperSuit = {version = "3.4.0", optional = true}
47
+ multi-agent-ale-py = {version = "0.1.11", optional = true}
48
+ boto3 = {version = "^1.24.70", optional = true}
49
+ awscli = {version = "^1.25.71", optional = true}
50
+ shimmy = {version = ">=1.0.0", extras = ["dm-control"], optional = true}
51
+
52
+ [tool.poetry.group.dev.dependencies]
53
+ pre-commit = "^2.20.0"
54
+
55
+
56
+ [tool.poetry.group.isaacgym]
57
+ optional = true
58
+ [tool.poetry.group.isaacgym.dependencies]
59
+ isaacgymenvs = {git = "https://github.com/vwxyzjn/IsaacGymEnvs.git", rev = "poetry", python = ">=3.7.1,<3.10"}
60
+ isaacgym = {path = "cleanrl/ppo_continuous_action_isaacgym/isaacgym", develop = true}
61
+
62
+
63
+ [build-system]
64
+ requires = ["poetry-core"]
65
+ build-backend = "poetry.core.masonry.api"
66
+
67
+ [tool.poetry.extras]
68
+ atari = ["ale-py", "AutoROM", "opencv-python"]
69
+ procgen = ["procgen"]
70
+ plot = ["pandas", "seaborn"]
71
+ pytest = ["pytest"]
72
+ mujoco = ["mujoco", "imageio"]
73
+ mujoco_py = ["free-mujoco-py"]
74
+ jax = ["jax", "jaxlib", "flax"]
75
+ docs = ["mkdocs-material", "markdown-include", "openrlbenchmark"]
76
+ envpool = ["envpool"]
77
+ optuna = ["optuna", "optuna-dashboard"]
78
+ pettingzoo = ["PettingZoo", "SuperSuit", "multi-agent-ale-py"]
79
+ cloud = ["boto3", "awscli"]
80
+ dm_control = ["shimmy", "mujoco"]
81
+
82
+ # dependencies for algorithm variant (useful when you want to run a specific algorithm)
83
+ dqn = []
84
+ dqn_atari = ["ale-py", "AutoROM", "opencv-python"]
85
+ dqn_jax = ["jax", "jaxlib", "flax"]
86
+ dqn_atari_jax = [
87
+ "ale-py", "AutoROM", "opencv-python", # atari
88
+ "jax", "jaxlib", "flax" # jax
89
+ ]
90
+ c51 = []
91
+ c51_atari = ["ale-py", "AutoROM", "opencv-python"]
92
+ c51_jax = ["jax", "jaxlib", "flax"]
93
+ c51_atari_jax = [
94
+ "ale-py", "AutoROM", "opencv-python", # atari
95
+ "jax", "jaxlib", "flax" # jax
96
+ ]
97
+ ppo_atari_envpool_xla_jax_scan = [
98
+ "ale-py", "AutoROM", "opencv-python", # atari
99
+ "jax", "jaxlib", "flax", # jax
100
+ "envpool", # envpool
101
+ ]
102
+ qdagger_dqn_atari_impalacnn = [
103
+ "ale-py", "AutoROM", "opencv-python"
104
+ ]
105
+ qdagger_dqn_atari_jax_impalacnn = [
106
+ "ale-py", "AutoROM", "opencv-python", # atari
107
+ "jax", "jaxlib", "flax", # jax
108
+ ]
replay.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e26af2785bb5c068112f893229a1de14560fc6755c077e5d28da2f3253686fe9
3
+ size 1526673
videos/HalfCheetah-v4__ppo_continuous_action__1__1697391142-eval/rl-video-episode-0.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5528bdfd3c2a21e978c9f7cca2488570307a0c1407443bb164b10351a2f8f1ce
3
+ size 3188142
videos/HalfCheetah-v4__ppo_continuous_action__1__1697391142-eval/rl-video-episode-1.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4781102cbdba6e73332cb7e61426d544b17e5c72100ece1e73c6cded18a4cc2a
3
+ size 2535902
videos/HalfCheetah-v4__ppo_continuous_action__1__1697391142-eval/rl-video-episode-8.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e26af2785bb5c068112f893229a1de14560fc6755c077e5d28da2f3253686fe9
3
+ size 1526673