tinybaselines 0.1.0a2__tar.gz → 0.1.0a3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tinybaselines-0.1.0a2/tinybaselines.egg-info → tinybaselines-0.1.0a3}/PKG-INFO +17 -5
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/README.md +16 -4
- tinybaselines-0.1.0a3/examples/cartpole/results/cpu.jsonl +4 -0
- tinybaselines-0.1.0a3/examples/cartpole/train.py +33 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/pyproject.toml +1 -1
- tinybaselines-0.1.0a3/tests/test_cartpole.py +39 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/tests/test_checkpoint.py +12 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/tests/test_core.py +23 -0
- tinybaselines-0.1.0a3/tests/test_learning.py +89 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/tinybaselines/__init__.py +1 -1
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/tinybaselines/policies.py +49 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/tinybaselines/ppo.py +11 -3
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/tinybaselines/rollout.py +1 -1
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3/tinybaselines.egg-info}/PKG-INFO +17 -5
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/tinybaselines.egg-info/SOURCES.txt +3 -0
- tinybaselines-0.1.0a2/tests/test_learning.py +0 -47
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/LICENSE +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/MANIFEST.in +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/__init__.py +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/lunar_lander/__init__.py +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/lunar_lander/config.py +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/lunar_lander/reference.py +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/lunar_lander/requirements-reference.txt +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/lunar_lander/requirements.txt +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/lunar_lander/results/2026-10-26/phase-initial-tinygrad-thread4.jsonl +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/lunar_lander/results/2026-10-26/phase-initial-torch.jsonl +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/lunar_lander/results/2026-10-26/phase-protocol.json +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/lunar_lander/results/2026-10-26/phase-tinygrad-thread10.jsonl +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/lunar_lander/results/2026-10-26/phase-tinygrad-thread4-error.jsonl +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/lunar_lander/results/2026-10-26/phase-torch-thread4.jsonl +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/lunar_lander/results/2026-10-26/protocol.json +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/lunar_lander/results/2026-10-26/tinygrad-cpu.jsonl +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/lunar_lander/results/2026-10-26/torch-cpu.jsonl +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/lunar_lander/run_learning.py +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/lunar_lander/train.py +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/pendulum/__init__.py +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/pendulum/env.py +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/pendulum/requirements.txt +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/pendulum/results/cpu-2.jsonl +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/pendulum/results/cpu-3.jsonl +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/pendulum/results/cpu.jsonl +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/pendulum/train.py +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/requirements.txt +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/setup.cfg +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/tests/test_evaluation.py +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/tests/test_learning_run.py +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/tests/test_parity.py +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/tests/test_pendulum.py +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/tests/test_rollout.py +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/tests/test_training.py +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/tinybaselines/evaluation.py +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/tinybaselines/training.py +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/tinybaselines.egg-info/dependency_links.txt +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/tinybaselines.egg-info/requires.txt +0 -0
- {tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/tinybaselines.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tinybaselines
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.0a3
|
|
4
4
|
Summary: PPO in tinygrad.
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -12,7 +12,7 @@ Dynamic: license-file
|
|
|
12
12
|
|
|
13
13
|
# tinybaselines
|
|
14
14
|
|
|
15
|
-
PPO in tinygrad. Continuous actions clipped to `[-1, 1]`.
|
|
15
|
+
PPO in tinygrad for discrete and continuous actions. Continuous actions are clipped to `[-1, 1]`.
|
|
16
16
|
|
|
17
17
|
## LunarLander from PyPI
|
|
18
18
|
|
|
@@ -21,7 +21,7 @@ Use Python 3.11 and clang. The library install does not include Gymnasium.
|
|
|
21
21
|
```sh
|
|
22
22
|
python3.11 -m venv .venv
|
|
23
23
|
source .venv/bin/activate
|
|
24
|
-
python -m pip install tinybaselines==0.1.
|
|
24
|
+
python -m pip install tinybaselines==0.1.0a3
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
Install Gymnasium and Box2D to run this example:
|
|
@@ -72,10 +72,10 @@ actions by default; `deterministic=True` uses clipped policy means.
|
|
|
72
72
|
The collector uses Gymnasium vector environments with same-step autoreset.
|
|
73
73
|
For time-limit bootstrapping, the collector reads pre-reset observations from `infos['final_obs']`.
|
|
74
74
|
|
|
75
|
-
PPO checkpoints contain the policy,
|
|
75
|
+
PPO checkpoints contain the policy, Adam state, and PPO settings.
|
|
76
76
|
Continue training by passing the loaded PPO to `learn` with a new transition budget.
|
|
77
77
|
Each `learn` call starts fresh episodes and a new transition counter.
|
|
78
|
-
`
|
|
78
|
+
`GaussianActorCritic.save(path)` exports a Gaussian policy for inference.
|
|
79
79
|
|
|
80
80
|
## Repository examples
|
|
81
81
|
|
|
@@ -86,6 +86,18 @@ pip install -e . -r examples/lunar_lander/requirements.txt
|
|
|
86
86
|
python -m examples.lunar_lander.train
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
+
CartPole uses `CategoricalActorCritic`. The example trains, saves a checkpoint,
|
|
90
|
+
and evaluates the reloaded policy over 10 episodes.
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
pip install -e . 'gymnasium==1.4.0'
|
|
94
|
+
DEV=CPU BEAM=0 python -m examples.cartpole.train --checkpoint cartpole.safetensors
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Three independent four-environment CPU runs averaged 500.00, 496.67, and 494.37
|
|
98
|
+
after 102,400 transitions each. All cleared 475 over 100 fresh stochastic episodes
|
|
99
|
+
per reloaded checkpoint. [Run records](examples/cartpole/results/cpu.jsonl).
|
|
100
|
+
|
|
89
101
|
Pendulum uses three observations and one action. Its example rescales policy actions
|
|
90
102
|
from `[-1, 1]` to torque in `[-2, 2]`.
|
|
91
103
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# tinybaselines
|
|
2
2
|
|
|
3
|
-
PPO in tinygrad. Continuous actions clipped to `[-1, 1]`.
|
|
3
|
+
PPO in tinygrad for discrete and continuous actions. Continuous actions are clipped to `[-1, 1]`.
|
|
4
4
|
|
|
5
5
|
## LunarLander from PyPI
|
|
6
6
|
|
|
@@ -9,7 +9,7 @@ Use Python 3.11 and clang. The library install does not include Gymnasium.
|
|
|
9
9
|
```sh
|
|
10
10
|
python3.11 -m venv .venv
|
|
11
11
|
source .venv/bin/activate
|
|
12
|
-
python -m pip install tinybaselines==0.1.
|
|
12
|
+
python -m pip install tinybaselines==0.1.0a3
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Install Gymnasium and Box2D to run this example:
|
|
@@ -60,10 +60,10 @@ actions by default; `deterministic=True` uses clipped policy means.
|
|
|
60
60
|
The collector uses Gymnasium vector environments with same-step autoreset.
|
|
61
61
|
For time-limit bootstrapping, the collector reads pre-reset observations from `infos['final_obs']`.
|
|
62
62
|
|
|
63
|
-
PPO checkpoints contain the policy,
|
|
63
|
+
PPO checkpoints contain the policy, Adam state, and PPO settings.
|
|
64
64
|
Continue training by passing the loaded PPO to `learn` with a new transition budget.
|
|
65
65
|
Each `learn` call starts fresh episodes and a new transition counter.
|
|
66
|
-
`
|
|
66
|
+
`GaussianActorCritic.save(path)` exports a Gaussian policy for inference.
|
|
67
67
|
|
|
68
68
|
## Repository examples
|
|
69
69
|
|
|
@@ -74,6 +74,18 @@ pip install -e . -r examples/lunar_lander/requirements.txt
|
|
|
74
74
|
python -m examples.lunar_lander.train
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
+
CartPole uses `CategoricalActorCritic`. The example trains, saves a checkpoint,
|
|
78
|
+
and evaluates the reloaded policy over 10 episodes.
|
|
79
|
+
|
|
80
|
+
```sh
|
|
81
|
+
pip install -e . 'gymnasium==1.4.0'
|
|
82
|
+
DEV=CPU BEAM=0 python -m examples.cartpole.train --checkpoint cartpole.safetensors
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Three independent four-environment CPU runs averaged 500.00, 496.67, and 494.37
|
|
86
|
+
after 102,400 transitions each. All cleared 475 over 100 fresh stochastic episodes
|
|
87
|
+
per reloaded checkpoint. [Run records](examples/cartpole/results/cpu.jsonl).
|
|
88
|
+
|
|
77
89
|
Pendulum uses three observations and one action. Its example rescales policy actions
|
|
78
90
|
from `[-1, 1]` to torque in `[-2, 2]`.
|
|
79
91
|
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
{"event": "config", "source_commit": "536bfa324af5ce2793a2332844af36b4033a6cb2", "environment": "CartPole-v1", "num_envs": 4, "seed": null, "requested_timesteps": 102400, "rollout_steps": 1024, "evaluation_episodes": 100, "deterministic": false, "acceptance_mean": 475, "policy": {"state_dim": 4, "action_dim": 2, "hidden_dim": 64, "actor_layers": 2, "critic_layers": 2}, "ppo": {"pi_lr": 0.0010000000474974513, "vf_lr": 0.0010000000474974513, "gamma": 0.99, "lamda": 0.95, "K_epochs": 4, "eps_clip": 0.2, "batch_size": 256, "vf_coef": 0.5, "entropy_coef": 0.01}, "device": "CPU", "cpu_threads": 10, "beam": "0", "jit": "1", "python": "3.11.14", "platform": "macOS-27.0.1-arm64-arm-64bit", "versions": {"tinygrad": "0.14.0", "numpy": "2.4.6", "gymnasium": "1.1.1"}}
|
|
2
|
+
{"event": "final", "run": 1, "timesteps": 102400, "mean_return": 500.0, "episode_returns": [500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0], "passed": true, "training_seconds": null, "evaluation_seconds": 14.94911529199453, "checkpoint": "run-1.safetensors", "note": "Repeated evaluation from the same checkpoint after a logging error."}
|
|
3
|
+
{"event": "final", "run": 2, "timesteps": 102400, "mean_return": 496.67, "episode_returns": [500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 390.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 445.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 332.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0], "passed": true, "training_seconds": 56.7557016669889, "evaluation_seconds": 16.15585825004382, "checkpoint": "run-2.safetensors"}
|
|
4
|
+
{"event": "final", "run": 3, "timesteps": 102400, "mean_return": 494.37, "episode_returns": [500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 96.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 341.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0], "passed": true, "training_seconds": 55.03045945899794, "evaluation_seconds": 16.498802624992095, "checkpoint": "run-3.safetensors"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
from contextlib import closing
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from statistics import mean
|
|
5
|
+
|
|
6
|
+
import gymnasium as gym
|
|
7
|
+
|
|
8
|
+
from tinybaselines import CategoricalActorCritic, PPO, evaluate, learn
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def main():
|
|
12
|
+
parser = argparse.ArgumentParser(description='Train PPO on CartPole-v1.')
|
|
13
|
+
parser.add_argument('--timesteps', type=int, default=40_960)
|
|
14
|
+
parser.add_argument('--checkpoint', type=Path, required=True)
|
|
15
|
+
args = parser.parse_args()
|
|
16
|
+
|
|
17
|
+
policy = CategoricalActorCritic(4, 2, 64, 2, 2)
|
|
18
|
+
ppo = PPO(policy, pi_lr=1e-3, vf_lr=1e-3, gamma=0.99, lamda=0.95, K_epochs=4,
|
|
19
|
+
eps_clip=0.2, batch_size=256, vf_coef=0.5, entropy_coef=0.01)
|
|
20
|
+
with closing(gym.vector.SyncVectorEnv(
|
|
21
|
+
[lambda: gym.make('CartPole-v1')] * 4,
|
|
22
|
+
autoreset_mode=gym.vector.AutoresetMode.SAME_STEP,
|
|
23
|
+
)) as env:
|
|
24
|
+
for step in learn(env, ppo, total_timesteps=args.timesteps, rollout_steps=1024):
|
|
25
|
+
print(f'{step.timesteps} transitions')
|
|
26
|
+
ppo.save(args.checkpoint)
|
|
27
|
+
policy = PPO.load(args.checkpoint).actor_critic
|
|
28
|
+
returns = evaluate(env, policy, num_episodes=10)
|
|
29
|
+
print(f'Mean return over {len(returns)} episodes: {mean(returns):.1f}')
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
if __name__ == '__main__':
|
|
33
|
+
main()
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from contextlib import closing
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from tempfile import TemporaryDirectory
|
|
4
|
+
import unittest
|
|
5
|
+
|
|
6
|
+
import gymnasium as gym
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
from tinybaselines import CategoricalActorCritic, PPO, evaluate, learn
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class CartPoleTest(unittest.TestCase):
|
|
13
|
+
def test_categorical_policy_trains_with_ppo(self):
|
|
14
|
+
policy = CategoricalActorCritic(4, 2, 16, 1, 1)
|
|
15
|
+
ppo = PPO(policy, pi_lr=1e-3, vf_lr=1e-3, gamma=0.99, lamda=0.95, K_epochs=2,
|
|
16
|
+
eps_clip=0.2, batch_size=64, vf_coef=0.5, entropy_coef=0.01)
|
|
17
|
+
weight = policy.actor.layers[-1].weight
|
|
18
|
+
before = weight.numpy().copy()
|
|
19
|
+
with closing(gym.vector.SyncVectorEnv([lambda: gym.make('CartPole-v1')] * 4,
|
|
20
|
+
autoreset_mode=gym.vector.AutoresetMode.SAME_STEP)) as env:
|
|
21
|
+
actions, _ = policy.act(env.reset()[0])
|
|
22
|
+
self.assertTrue(env.action_space.contains(actions))
|
|
23
|
+
steps = list(learn(env, ppo, total_timesteps=384, rollout_steps=128))
|
|
24
|
+
self.assertEqual(steps[-1].timesteps, 384)
|
|
25
|
+
self.assertFalse(np.array_equal(weight.numpy(), before))
|
|
26
|
+
observations, _ = env.reset()
|
|
27
|
+
with TemporaryDirectory() as directory:
|
|
28
|
+
path = Path(directory) / 'ppo.safetensors'
|
|
29
|
+
ppo.save(path)
|
|
30
|
+
restored = PPO.load(path)
|
|
31
|
+
self.assertIsInstance(restored.actor_critic, CategoricalActorCritic)
|
|
32
|
+
np.testing.assert_array_equal(restored.actor_critic.act(observations, deterministic=True)[0],
|
|
33
|
+
policy.act(observations, deterministic=True)[0])
|
|
34
|
+
state = restored.state_dict()
|
|
35
|
+
self.assertEqual(state.keys(), ppo.state_dict().keys())
|
|
36
|
+
for name, tensor in ppo.state_dict().items():
|
|
37
|
+
np.testing.assert_array_equal(state[name].numpy(), tensor.numpy())
|
|
38
|
+
self.assertEqual(len(evaluate(env, restored.actor_critic, num_episodes=8)), 8)
|
|
39
|
+
self.assertEqual(next(learn(env, restored, total_timesteps=128, rollout_steps=128)).timesteps, 128)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import json
|
|
1
2
|
import tempfile
|
|
2
3
|
import unittest
|
|
3
4
|
from pathlib import Path
|
|
@@ -83,6 +84,17 @@ class CheckpointTest(unittest.TestCase):
|
|
|
83
84
|
np.testing.assert_array_equal(first.actor_critic.log_std.numpy(), before)
|
|
84
85
|
np.testing.assert_array_equal(second.actor_critic.log_std.numpy(), [0.25])
|
|
85
86
|
|
|
87
|
+
def test_loads_gaussian_checkpoint_without_policy_type(self):
|
|
88
|
+
ppo = self.make_ppo()
|
|
89
|
+
metadata = dict(format='tinybaselines.ppo.v1', policy_config=json.dumps(ppo.actor_critic.config),
|
|
90
|
+
ppo_config=json.dumps(ppo.config))
|
|
91
|
+
with tempfile.TemporaryDirectory() as directory:
|
|
92
|
+
path = Path(directory) / 'legacy.safetensors'
|
|
93
|
+
lander.nn.state.safe_save(ppo.state_dict(), path, metadata=metadata)
|
|
94
|
+
restored = PPO.load(path)
|
|
95
|
+
self.assertIsInstance(restored.actor_critic, GaussianActorCritic)
|
|
96
|
+
np.testing.assert_array_equal(restored.actor_critic.observation_scale.numpy(), [2, 3, 4])
|
|
97
|
+
|
|
86
98
|
def test_failed_save_preserves_previous_checkpoint(self):
|
|
87
99
|
ppo = self.make_ppo()
|
|
88
100
|
|
|
@@ -6,12 +6,35 @@ import unittest
|
|
|
6
6
|
from unittest.mock import patch
|
|
7
7
|
|
|
8
8
|
import numpy as np
|
|
9
|
+
from tinygrad import Tensor
|
|
9
10
|
|
|
10
11
|
from tinybaselines import GaussianActorCritic, PPO, rollout
|
|
11
12
|
from tinybaselines.rollout import RolloutBatch
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class CoreTest(unittest.TestCase):
|
|
16
|
+
def test_action_dtype_and_shape_survive_minibatching(self):
|
|
17
|
+
observations = np.zeros((4, 3), np.float32)
|
|
18
|
+
done = np.zeros(4, bool)
|
|
19
|
+
env = SimpleNamespace(num_envs=4, reset=lambda: (observations, {}),
|
|
20
|
+
step=lambda actions: (observations, np.ones(4), done, done, {}))
|
|
21
|
+
policy = GaussianActorCritic(3, 2, 4, 1, 1)
|
|
22
|
+
ppo = PPO(policy, pi_lr=1e-3, vf_lr=1e-3, gamma=0.99, lamda=0.95, K_epochs=1,
|
|
23
|
+
eps_clip=0.2, batch_size=4, vf_coef=1.0, entropy_coef=0.0)
|
|
24
|
+
values = Tensor.zeros(8, 1, device=policy.device)
|
|
25
|
+
for actions in (np.arange(4, dtype=np.int32), np.arange(8, dtype=np.float32).reshape(4, 2) / 8):
|
|
26
|
+
with self.subTest(dtype=actions.dtype, shape=actions.shape):
|
|
27
|
+
with patch.object(policy, 'act', return_value=(actions, actions)):
|
|
28
|
+
batch, _ = rollout(env, policy, num_steps=8)
|
|
29
|
+
self.assertEqual(batch.raw_actions.dtype, actions.dtype)
|
|
30
|
+
np.testing.assert_array_equal(batch.raw_actions, np.stack([actions, actions]))
|
|
31
|
+
with patch.object(policy, 'evaluate_actions', return_value=(values, values.squeeze(-1), None)), \
|
|
32
|
+
patch.object(ppo, 'train_step') as step, patch('numpy.random.permutation', return_value=np.arange(8)):
|
|
33
|
+
ppo.update(batch)
|
|
34
|
+
minibatches = np.concatenate([call.args[1].numpy() for call in step.call_args_list])
|
|
35
|
+
self.assertEqual(minibatches.dtype, actions.dtype)
|
|
36
|
+
np.testing.assert_array_equal(minibatches, np.concatenate([actions, actions]))
|
|
37
|
+
|
|
15
38
|
def test_ppo_gets_actor_parameters_and_device_from_policy(self):
|
|
16
39
|
model = GaussianActorCritic(3, 1, 4, 1, 1)
|
|
17
40
|
weight = model.actor.layers[0].weight
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from tinygrad import Tensor
|
|
5
|
+
|
|
6
|
+
from tinybaselines import CategoricalActorCritic, GaussianActorCritic, PPO, learn
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class IdentityEnv:
|
|
10
|
+
num_envs = 4
|
|
11
|
+
|
|
12
|
+
def __init__(self, seed):
|
|
13
|
+
self.rng = np.random.default_rng(seed)
|
|
14
|
+
|
|
15
|
+
def reset(self):
|
|
16
|
+
self.observations = self.rng.uniform(-0.75, 0.75, (self.num_envs, 1)).astype(np.float32)
|
|
17
|
+
return self.observations, {}
|
|
18
|
+
|
|
19
|
+
def step(self, actions):
|
|
20
|
+
rewards = -np.square(actions[:, 0] - self.observations[:, 0])
|
|
21
|
+
observations, _ = self.reset()
|
|
22
|
+
return observations, rewards, np.ones(self.num_envs, bool), np.zeros(self.num_envs, bool), {}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def identity_errors(seed):
|
|
26
|
+
Tensor.manual_seed(seed)
|
|
27
|
+
np.random.seed(seed)
|
|
28
|
+
policy = GaussianActorCritic(1, 1, 16, 1, 1)
|
|
29
|
+
ppo = PPO(policy, pi_lr=0.01, vf_lr=0.01, gamma=0.99, lamda=0.95, K_epochs=4,
|
|
30
|
+
eps_clip=0.2, batch_size=256, vf_coef=0.5, entropy_coef=0.0)
|
|
31
|
+
observations = np.linspace(-0.75, 0.75, 65, dtype=np.float32)[:, None]
|
|
32
|
+
|
|
33
|
+
def error():
|
|
34
|
+
actions, _ = policy.act(observations, deterministic=True)
|
|
35
|
+
return np.square(actions - observations).mean()
|
|
36
|
+
|
|
37
|
+
before = error()
|
|
38
|
+
for _ in learn(IdentityEnv(seed), ppo, total_timesteps=2048, rollout_steps=256):
|
|
39
|
+
pass
|
|
40
|
+
return before, error(), np.square(observations).mean()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class DiscreteIdentityEnv:
|
|
44
|
+
num_envs = 4
|
|
45
|
+
observations = np.eye(4, dtype=np.float32)
|
|
46
|
+
|
|
47
|
+
def __init__(self, seed):
|
|
48
|
+
self.rng = np.random.default_rng(seed)
|
|
49
|
+
|
|
50
|
+
def reset(self):
|
|
51
|
+
self.targets = self.rng.integers(4, size=self.num_envs)
|
|
52
|
+
return self.observations[self.targets], {}
|
|
53
|
+
|
|
54
|
+
def step(self, actions):
|
|
55
|
+
rewards = (actions == self.targets).astype(np.float32)
|
|
56
|
+
observations, _ = self.reset()
|
|
57
|
+
return observations, rewards, np.ones(self.num_envs, bool), np.zeros(self.num_envs, bool), {}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def discrete_identity_scores(seed):
|
|
61
|
+
Tensor.manual_seed(seed)
|
|
62
|
+
np.random.seed(seed)
|
|
63
|
+
env = DiscreteIdentityEnv(seed)
|
|
64
|
+
policy = CategoricalActorCritic(4, 4, 16, 1, 1)
|
|
65
|
+
ppo = PPO(policy, pi_lr=0.02, vf_lr=0.01, gamma=0.99, lamda=0.95, K_epochs=4,
|
|
66
|
+
eps_clip=0.2, batch_size=64, vf_coef=0.5, entropy_coef=0.0)
|
|
67
|
+
states = policy.preprocess(env.observations)
|
|
68
|
+
targets = Tensor(np.arange(4, dtype=np.int32), device=policy.device)
|
|
69
|
+
|
|
70
|
+
def score():
|
|
71
|
+
_, log_probs, _ = policy.evaluate_actions(states, targets)
|
|
72
|
+
return log_probs.exp().mean().item()
|
|
73
|
+
|
|
74
|
+
before = score()
|
|
75
|
+
for _ in learn(env, ppo, total_timesteps=1024, rollout_steps=128):
|
|
76
|
+
pass
|
|
77
|
+
return before, score()
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class LearningTest(unittest.TestCase):
|
|
81
|
+
def test_learns_identity(self):
|
|
82
|
+
self.addCleanup(np.random.set_state, np.random.get_state())
|
|
83
|
+
before, after, zero = identity_errors(seed=0)
|
|
84
|
+
self.assertLess(after, 0.25 * min(before, zero), (before, after, zero))
|
|
85
|
+
|
|
86
|
+
def test_learns_discrete_identity(self):
|
|
87
|
+
self.addCleanup(np.random.set_state, np.random.get_state())
|
|
88
|
+
before, after = discrete_identity_scores(seed=0)
|
|
89
|
+
self.assertGreater(after, max(before, 0.9), (before, after))
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from .ppo import PPO
|
|
2
|
-
from .policies import GaussianActorCritic
|
|
2
|
+
from .policies import CategoricalActorCritic, GaussianActorCritic
|
|
3
3
|
from .rollout import RolloutBatch, RolloutState, rollout
|
|
4
4
|
from .training import TrainingStep, learn
|
|
5
5
|
from .evaluation import evaluate
|
|
@@ -25,6 +25,8 @@ class MLP:
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class GaussianActorCritic:
|
|
28
|
+
_checkpoint_type = 'gaussian'
|
|
29
|
+
|
|
28
30
|
def __init__(self, state_dim, action_dim, hidden_dim, actor_layers, critic_layers, observation_scale=None):
|
|
29
31
|
self.config = dict(state_dim=state_dim, action_dim=action_dim, hidden_dim=hidden_dim,
|
|
30
32
|
actor_layers=actor_layers, critic_layers=critic_layers)
|
|
@@ -96,3 +98,50 @@ class GaussianActorCritic:
|
|
|
96
98
|
self.action_std = np.exp(self.log_std.clip(-5, 2).numpy())
|
|
97
99
|
if not np.isfinite(self.action_std).all():
|
|
98
100
|
raise FloatingPointError('non-finite policy standard deviation')
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class CategoricalActorCritic:
|
|
104
|
+
"""Actor-critic for a single discrete action per observation."""
|
|
105
|
+
|
|
106
|
+
_checkpoint_type = 'categorical'
|
|
107
|
+
|
|
108
|
+
def __init__(self, state_dim, action_dim, hidden_dim, actor_layers, critic_layers):
|
|
109
|
+
self.config = dict(state_dim=state_dim, action_dim=action_dim, hidden_dim=hidden_dim,
|
|
110
|
+
actor_layers=actor_layers, critic_layers=critic_layers)
|
|
111
|
+
self.actor = MLP(state_dim, action_dim, hidden_dim, actor_layers)
|
|
112
|
+
self.critic = MLP(state_dim, 1, hidden_dim, critic_layers)
|
|
113
|
+
self.actor_jit = TinyJit(lambda states: self.actor(states).realize())
|
|
114
|
+
self.jit_shape = None
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def actor_parameters(self):
|
|
118
|
+
return nn.state.get_parameters(self.actor)
|
|
119
|
+
|
|
120
|
+
@property
|
|
121
|
+
def device(self):
|
|
122
|
+
return self.actor.layers[0].weight.device
|
|
123
|
+
|
|
124
|
+
def preprocess(self, observations):
|
|
125
|
+
return Tensor(observations.astype(np.float32), device=self.device)
|
|
126
|
+
|
|
127
|
+
def evaluate_actions(self, states, actions):
|
|
128
|
+
log_probs = self.actor(states).log_softmax(axis=-1)
|
|
129
|
+
selected = log_probs.gather(-1, actions.unsqueeze(-1)).squeeze(-1)
|
|
130
|
+
entropy = -(log_probs.exp() * log_probs).sum(axis=-1).mean()
|
|
131
|
+
return self.critic(states), selected, entropy
|
|
132
|
+
|
|
133
|
+
def act(self, state, deterministic=False):
|
|
134
|
+
states = self.preprocess(state)
|
|
135
|
+
if self.jit_shape != states.shape:
|
|
136
|
+
self.refresh_inference()
|
|
137
|
+
self.jit_shape = states.shape
|
|
138
|
+
logits = self.actor_jit(states).numpy()
|
|
139
|
+
scores = logits if deterministic else logits + np.random.gumbel(size=logits.shape)
|
|
140
|
+
actions = scores.argmax(axis=-1).astype(np.int32)
|
|
141
|
+
return actions, actions
|
|
142
|
+
|
|
143
|
+
def refresh_inference(self):
|
|
144
|
+
self.actor_jit.reset()
|
|
145
|
+
|
|
146
|
+
def state_dict(self):
|
|
147
|
+
return nn.state.get_state_dict(dict(actor=self.actor, critic=self.critic))
|
|
@@ -5,7 +5,10 @@ from tempfile import TemporaryDirectory
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
from tinygrad import Context, Tensor, TinyJit, nn
|
|
7
7
|
|
|
8
|
-
from .policies import GaussianActorCritic
|
|
8
|
+
from .policies import CategoricalActorCritic, GaussianActorCritic
|
|
9
|
+
|
|
10
|
+
_CHECKPOINT_POLICIES = {policy._checkpoint_type: policy for policy in (GaussianActorCritic, CategoricalActorCritic)}
|
|
11
|
+
|
|
9
12
|
|
|
10
13
|
def clip_grad_norm(parameters, max_norm):
|
|
11
14
|
gradients = [parameter.grad for parameter in parameters if parameter.grad is not None]
|
|
@@ -52,6 +55,7 @@ class PPO:
|
|
|
52
55
|
def save(self, path):
|
|
53
56
|
path = Path(path)
|
|
54
57
|
metadata = dict(format='tinybaselines.ppo.v1', policy_config=json.dumps(self.actor_critic.config),
|
|
58
|
+
policy_type=self.actor_critic._checkpoint_type,
|
|
55
59
|
ppo_config=json.dumps(self.config))
|
|
56
60
|
with TemporaryDirectory(dir=path.parent) as directory:
|
|
57
61
|
temporary = Path(directory) / path.name
|
|
@@ -64,7 +68,11 @@ class PPO:
|
|
|
64
68
|
metadata = header.get('__metadata__', {})
|
|
65
69
|
if metadata.get('format') != 'tinybaselines.ppo.v1':
|
|
66
70
|
raise ValueError('unsupported PPO checkpoint format')
|
|
67
|
-
|
|
71
|
+
policy_type = metadata.get('policy_type', 'gaussian')
|
|
72
|
+
policy_class = _CHECKPOINT_POLICIES.get(policy_type)
|
|
73
|
+
if policy_class is None:
|
|
74
|
+
raise ValueError(f'unsupported PPO checkpoint policy type: {policy_type!r}')
|
|
75
|
+
policy = policy_class(**json.loads(metadata['policy_config']))
|
|
68
76
|
ppo = cls(policy, **json.loads(metadata['ppo_config']))
|
|
69
77
|
nn.state.load_state_dict(ppo.state_dict(), nn.state.safe_load(path), verbose=False)
|
|
70
78
|
policy.refresh_inference()
|
|
@@ -114,7 +122,7 @@ class PPO:
|
|
|
114
122
|
def prepare(self, batch):
|
|
115
123
|
T, N = batch.rewards.shape
|
|
116
124
|
obs_flat = self.actor_critic.preprocess(batch.observations.reshape(T * N, -1))
|
|
117
|
-
raw_act_np = batch.raw_actions.reshape(T * N,
|
|
125
|
+
raw_act_np = batch.raw_actions.reshape(T * N, *batch.raw_actions.shape[2:])
|
|
118
126
|
raw_act_flat = Tensor(raw_act_np, device=self.device)
|
|
119
127
|
old_value, old_logprobs, _ = self.actor_critic.evaluate_actions(obs_flat, raw_act_flat)
|
|
120
128
|
old_logprobs_np = old_logprobs.numpy()
|
|
@@ -58,7 +58,7 @@ def rollout(env, actor_critic, num_steps=None, num_episodes=None, deterministic=
|
|
|
58
58
|
actions, raw_actions = actor_critic.act(states, deterministic=deterministic)
|
|
59
59
|
if collect:
|
|
60
60
|
if t == 0:
|
|
61
|
-
raw_act = np.empty((T, *raw_actions.shape), dtype=
|
|
61
|
+
raw_act = np.empty((T, *raw_actions.shape), dtype=raw_actions.dtype)
|
|
62
62
|
obs[t], raw_act[t] = states, raw_actions
|
|
63
63
|
|
|
64
64
|
states, rewards, terminated, truncated, infos = env.step(actions)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tinybaselines
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.0a3
|
|
4
4
|
Summary: PPO in tinygrad.
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -12,7 +12,7 @@ Dynamic: license-file
|
|
|
12
12
|
|
|
13
13
|
# tinybaselines
|
|
14
14
|
|
|
15
|
-
PPO in tinygrad. Continuous actions clipped to `[-1, 1]`.
|
|
15
|
+
PPO in tinygrad for discrete and continuous actions. Continuous actions are clipped to `[-1, 1]`.
|
|
16
16
|
|
|
17
17
|
## LunarLander from PyPI
|
|
18
18
|
|
|
@@ -21,7 +21,7 @@ Use Python 3.11 and clang. The library install does not include Gymnasium.
|
|
|
21
21
|
```sh
|
|
22
22
|
python3.11 -m venv .venv
|
|
23
23
|
source .venv/bin/activate
|
|
24
|
-
python -m pip install tinybaselines==0.1.
|
|
24
|
+
python -m pip install tinybaselines==0.1.0a3
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
Install Gymnasium and Box2D to run this example:
|
|
@@ -72,10 +72,10 @@ actions by default; `deterministic=True` uses clipped policy means.
|
|
|
72
72
|
The collector uses Gymnasium vector environments with same-step autoreset.
|
|
73
73
|
For time-limit bootstrapping, the collector reads pre-reset observations from `infos['final_obs']`.
|
|
74
74
|
|
|
75
|
-
PPO checkpoints contain the policy,
|
|
75
|
+
PPO checkpoints contain the policy, Adam state, and PPO settings.
|
|
76
76
|
Continue training by passing the loaded PPO to `learn` with a new transition budget.
|
|
77
77
|
Each `learn` call starts fresh episodes and a new transition counter.
|
|
78
|
-
`
|
|
78
|
+
`GaussianActorCritic.save(path)` exports a Gaussian policy for inference.
|
|
79
79
|
|
|
80
80
|
## Repository examples
|
|
81
81
|
|
|
@@ -86,6 +86,18 @@ pip install -e . -r examples/lunar_lander/requirements.txt
|
|
|
86
86
|
python -m examples.lunar_lander.train
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
+
CartPole uses `CategoricalActorCritic`. The example trains, saves a checkpoint,
|
|
90
|
+
and evaluates the reloaded policy over 10 episodes.
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
pip install -e . 'gymnasium==1.4.0'
|
|
94
|
+
DEV=CPU BEAM=0 python -m examples.cartpole.train --checkpoint cartpole.safetensors
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Three independent four-environment CPU runs averaged 500.00, 496.67, and 494.37
|
|
98
|
+
after 102,400 transitions each. All cleared 475 over 100 fresh stochastic episodes
|
|
99
|
+
per reloaded checkpoint. [Run records](examples/cartpole/results/cpu.jsonl).
|
|
100
|
+
|
|
89
101
|
Pendulum uses three observations and one action. Its example rescales policy actions
|
|
90
102
|
from `[-1, 1]` to torque in `[-2, 2]`.
|
|
91
103
|
|
|
@@ -4,6 +4,8 @@ README.md
|
|
|
4
4
|
pyproject.toml
|
|
5
5
|
requirements.txt
|
|
6
6
|
examples/__init__.py
|
|
7
|
+
examples/cartpole/train.py
|
|
8
|
+
examples/cartpole/results/cpu.jsonl
|
|
7
9
|
examples/lunar_lander/__init__.py
|
|
8
10
|
examples/lunar_lander/config.py
|
|
9
11
|
examples/lunar_lander/reference.py
|
|
@@ -27,6 +29,7 @@ examples/pendulum/train.py
|
|
|
27
29
|
examples/pendulum/results/cpu-2.jsonl
|
|
28
30
|
examples/pendulum/results/cpu-3.jsonl
|
|
29
31
|
examples/pendulum/results/cpu.jsonl
|
|
32
|
+
tests/test_cartpole.py
|
|
30
33
|
tests/test_checkpoint.py
|
|
31
34
|
tests/test_core.py
|
|
32
35
|
tests/test_evaluation.py
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import unittest
|
|
2
|
-
|
|
3
|
-
import numpy as np
|
|
4
|
-
from tinygrad import Tensor
|
|
5
|
-
|
|
6
|
-
from tinybaselines import GaussianActorCritic, PPO, learn
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class IdentityEnv:
|
|
10
|
-
num_envs = 4
|
|
11
|
-
|
|
12
|
-
def __init__(self, seed):
|
|
13
|
-
self.rng = np.random.default_rng(seed)
|
|
14
|
-
|
|
15
|
-
def reset(self):
|
|
16
|
-
self.observations = self.rng.uniform(-0.75, 0.75, (self.num_envs, 1)).astype(np.float32)
|
|
17
|
-
return self.observations, {}
|
|
18
|
-
|
|
19
|
-
def step(self, actions):
|
|
20
|
-
rewards = -np.square(actions[:, 0] - self.observations[:, 0])
|
|
21
|
-
observations, _ = self.reset()
|
|
22
|
-
return observations, rewards, np.ones(self.num_envs, bool), np.zeros(self.num_envs, bool), {}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def identity_errors(seed):
|
|
26
|
-
Tensor.manual_seed(seed)
|
|
27
|
-
np.random.seed(seed)
|
|
28
|
-
policy = GaussianActorCritic(1, 1, 16, 1, 1)
|
|
29
|
-
ppo = PPO(policy, pi_lr=0.01, vf_lr=0.01, gamma=0.99, lamda=0.95, K_epochs=4,
|
|
30
|
-
eps_clip=0.2, batch_size=256, vf_coef=0.5, entropy_coef=0.0)
|
|
31
|
-
observations = np.linspace(-0.75, 0.75, 65, dtype=np.float32)[:, None]
|
|
32
|
-
|
|
33
|
-
def error():
|
|
34
|
-
actions, _ = policy.act(observations, deterministic=True)
|
|
35
|
-
return np.square(actions - observations).mean()
|
|
36
|
-
|
|
37
|
-
before = error()
|
|
38
|
-
for _ in learn(IdentityEnv(seed), ppo, total_timesteps=2048, rollout_steps=256):
|
|
39
|
-
pass
|
|
40
|
-
return before, error(), np.square(observations).mean()
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
class LearningTest(unittest.TestCase):
|
|
44
|
-
def test_learns_identity(self):
|
|
45
|
-
self.addCleanup(np.random.set_state, np.random.get_state())
|
|
46
|
-
before, after, zero = identity_errors(seed=0)
|
|
47
|
-
self.assertLess(after, 0.25 * min(before, zero), (before, after, zero))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybaselines-0.1.0a2 → tinybaselines-0.1.0a3}/examples/lunar_lander/requirements-reference.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|