evolutionary-policy-optimization 0.3.5__tar.gz → 0.4.1__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.
- {evolutionary_policy_optimization-0.3.5 → evolutionary_policy_optimization-0.4.1}/.gitignore +12 -0
- {evolutionary_policy_optimization-0.3.5 → evolutionary_policy_optimization-0.4.1}/PKG-INFO +12 -2
- {evolutionary_policy_optimization-0.3.5 → evolutionary_policy_optimization-0.4.1}/README.md +10 -0
- {evolutionary_policy_optimization-0.3.5 → evolutionary_policy_optimization-0.4.1}/evolutionary_policy_optimization/__init__.py +1 -1
- {evolutionary_policy_optimization-0.3.5 → evolutionary_policy_optimization-0.4.1}/evolutionary_policy_optimization/epo.py +67 -16
- {evolutionary_policy_optimization-0.3.5 → evolutionary_policy_optimization-0.4.1}/pyproject.toml +2 -2
- {evolutionary_policy_optimization-0.3.5 → evolutionary_policy_optimization-0.4.1}/LICENSE +0 -0
- {evolutionary_policy_optimization-0.3.5 → evolutionary_policy_optimization-0.4.1}/evolutionary_policy_optimization/distributed.py +0 -0
- {evolutionary_policy_optimization-0.3.5 → evolutionary_policy_optimization-0.4.1}/evolutionary_policy_optimization/env_wrappers.py +0 -0
- {evolutionary_policy_optimization-0.3.5 → evolutionary_policy_optimization-0.4.1}/evolutionary_policy_optimization/experimental.py +0 -0
- {evolutionary_policy_optimization-0.3.5 → evolutionary_policy_optimization-0.4.1}/evolutionary_policy_optimization/mock_env.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: evolutionary-policy-optimization
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: EPO - Pytorch
|
|
5
5
|
Project-URL: Homepage, https://pypi.org/project/evolutionary-policy-optimization/
|
|
6
6
|
Project-URL: Repository, https://github.com/lucidrains/evolutionary-policy-optimization
|
|
@@ -40,7 +40,7 @@ Requires-Dist: einops>=0.8.1
|
|
|
40
40
|
Requires-Dist: einx>=0.3.0
|
|
41
41
|
Requires-Dist: ema-pytorch>=0.7.7
|
|
42
42
|
Requires-Dist: hl-gauss-pytorch>=0.2.8
|
|
43
|
-
Requires-Dist: mean-conc-beta>=0.
|
|
43
|
+
Requires-Dist: mean-conc-beta>=0.2.7
|
|
44
44
|
Requires-Dist: torch>=2.2
|
|
45
45
|
Requires-Dist: tqdm
|
|
46
46
|
Requires-Dist: x-mlps-pytorch>=0.3.0
|
|
@@ -367,6 +367,16 @@ That's it
|
|
|
367
367
|
}
|
|
368
368
|
```
|
|
369
369
|
|
|
370
|
+
```bibtex
|
|
371
|
+
@inproceedings{Sharma2020DynamicsAwareUD,
|
|
372
|
+
title = {Dynamics-Aware Unsupervised Discovery of Skills},
|
|
373
|
+
author = {Archit Sharma and Shixiang Gu and Sergey Levine and Vikash Kumar and Karol Hausman},
|
|
374
|
+
booktitle = {International Conference on Learning Representations},
|
|
375
|
+
year = {2020},
|
|
376
|
+
url = {https://arxiv.org/abs/1907.01657}
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
370
380
|
```bibtex
|
|
371
381
|
@article{Zhu2025Hybrid,
|
|
372
382
|
author = {Zhu, Zimo and Yu, Chuanqiang and Wang, Junti},
|
|
@@ -305,6 +305,16 @@ That's it
|
|
|
305
305
|
}
|
|
306
306
|
```
|
|
307
307
|
|
|
308
|
+
```bibtex
|
|
309
|
+
@inproceedings{Sharma2020DynamicsAwareUD,
|
|
310
|
+
title = {Dynamics-Aware Unsupervised Discovery of Skills},
|
|
311
|
+
author = {Archit Sharma and Shixiang Gu and Sergey Levine and Vikash Kumar and Karol Hausman},
|
|
312
|
+
booktitle = {International Conference on Learning Representations},
|
|
313
|
+
year = {2020},
|
|
314
|
+
url = {https://arxiv.org/abs/1907.01657}
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
308
318
|
```bibtex
|
|
309
319
|
@article{Zhu2025Hybrid,
|
|
310
320
|
author = {Zhu, Zimo and Yu, Chuanqiang and Wang, Junti},
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
from evolutionary_policy_optimization.env_wrappers import GymnasiumEnvWrapper, rescale_from_to
|
|
2
|
-
from evolutionary_policy_optimization.epo import EPO, MLP, Actor, Agent, Beta, CategoricalActionDistr, Critic, LatentGenePool, create_agent
|
|
2
|
+
from evolutionary_policy_optimization.epo import EPO, MLP, Actor, Agent, Beta, CategoricalActionDistr, Critic, DiversityDiscr, LatentGenePool, create_agent
|
|
3
3
|
from evolutionary_policy_optimization.mock_env import Env, VectorEnv
|
|
@@ -52,6 +52,20 @@ def divisible_by(num, den):
|
|
|
52
52
|
def to_device(inp, device):
|
|
53
53
|
return tree_map(lambda t: t.to(device) if is_tensor(t) else t, inp)
|
|
54
54
|
|
|
55
|
+
class ShuffledBatches:
|
|
56
|
+
# fresh permutation on every pass
|
|
57
|
+
|
|
58
|
+
def __init__(self, fields, batch_size):
|
|
59
|
+
self.fields = fields
|
|
60
|
+
self.batch_size = batch_size
|
|
61
|
+
|
|
62
|
+
def __iter__(self):
|
|
63
|
+
perm = torch.randperm(self.fields[0].shape[0])
|
|
64
|
+
|
|
65
|
+
for i in range(0, len(perm), self.batch_size):
|
|
66
|
+
b = perm[i:i + self.batch_size]
|
|
67
|
+
yield [field[b] for field in self.fields]
|
|
68
|
+
|
|
55
69
|
def maybe(fn):
|
|
56
70
|
|
|
57
71
|
@wraps(fn)
|
|
@@ -513,7 +527,7 @@ class MLP(Module):
|
|
|
513
527
|
|
|
514
528
|
return self.final_lime(x, prev_layer_inputs)
|
|
515
529
|
|
|
516
|
-
# discriminator for predicting latent code from states
|
|
530
|
+
# discriminator for predicting latent code from states or state transitions (DIAYN / DADS)
|
|
517
531
|
|
|
518
532
|
class DiversityDiscr(Module):
|
|
519
533
|
def __init__(
|
|
@@ -521,15 +535,19 @@ class DiversityDiscr(Module):
|
|
|
521
535
|
dim_state,
|
|
522
536
|
num_latents,
|
|
523
537
|
dim = 64,
|
|
524
|
-
depth = 2
|
|
538
|
+
depth = 2,
|
|
539
|
+
time_gap = 1
|
|
525
540
|
):
|
|
526
541
|
super().__init__()
|
|
542
|
+
self.time_gap = time_gap
|
|
543
|
+
self.state_transition = time_gap > 0
|
|
544
|
+
|
|
527
545
|
self.state_proj = nn.Linear(dim_state, dim)
|
|
528
546
|
|
|
529
547
|
self.net = AttnResidualNormedMLP(
|
|
530
548
|
dim = dim,
|
|
531
549
|
depth = depth,
|
|
532
|
-
dim_in = dim * 2,
|
|
550
|
+
dim_in = dim * 2 if self.state_transition else dim,
|
|
533
551
|
dim_out = num_latents
|
|
534
552
|
)
|
|
535
553
|
|
|
@@ -538,8 +556,12 @@ class DiversityDiscr(Module):
|
|
|
538
556
|
if isinstance(module, (nn.Linear, nn.LayerNorm, nn.RMSNorm)):
|
|
539
557
|
module.reset_parameters()
|
|
540
558
|
|
|
541
|
-
def forward(self, state, next_state):
|
|
559
|
+
def forward(self, state, next_state = None):
|
|
542
560
|
state_embed = self.state_proj(state)
|
|
561
|
+
|
|
562
|
+
if not self.state_transition or not exists(next_state):
|
|
563
|
+
return self.net(state_embed)
|
|
564
|
+
|
|
543
565
|
next_state_embed = self.state_proj(next_state)
|
|
544
566
|
return self.net((state_embed, next_state_embed))
|
|
545
567
|
|
|
@@ -1215,6 +1237,7 @@ class Agent(Module):
|
|
|
1215
1237
|
critic_optim_kwargs: dict = dict(),
|
|
1216
1238
|
latent_optim_kwargs: dict = dict(),
|
|
1217
1239
|
use_diversity_discr = False,
|
|
1240
|
+
diversity_time_gap = 1, # 0 for DIAYN (state only), >= 1 for DADS (state transition with given time gap)
|
|
1218
1241
|
diversity_discr_kwargs: dict = dict(dim = 64, depth = 2),
|
|
1219
1242
|
diversity_discr_lr = 3e-4,
|
|
1220
1243
|
diversity_discr_optim_kwargs: dict = dict(),
|
|
@@ -1225,6 +1248,7 @@ class Agent(Module):
|
|
|
1225
1248
|
hidden_spr_ema_update = 0.99,
|
|
1226
1249
|
get_fitness_scores: Callable[..., Tensor] = get_fitness_scores,
|
|
1227
1250
|
wrap_with_accelerate: bool = True,
|
|
1251
|
+
use_dataloader = False,
|
|
1228
1252
|
accelerate_kwargs: dict = dict(),
|
|
1229
1253
|
accelerator = None,
|
|
1230
1254
|
quiet: bool = False,
|
|
@@ -1236,6 +1260,7 @@ class Agent(Module):
|
|
|
1236
1260
|
# hf accelerate
|
|
1237
1261
|
|
|
1238
1262
|
self.wrap_with_accelerate = wrap_with_accelerate
|
|
1263
|
+
self.use_dataloader = use_dataloader
|
|
1239
1264
|
|
|
1240
1265
|
if wrap_with_accelerate:
|
|
1241
1266
|
self.accelerate = accelerator if exists(accelerator) else Accelerator(**accelerate_kwargs)
|
|
@@ -1305,14 +1330,16 @@ class Agent(Module):
|
|
|
1305
1330
|
# diversity discriminator
|
|
1306
1331
|
|
|
1307
1332
|
self.use_diversity_discr = use_diversity_discr
|
|
1333
|
+
self.diversity_time_gap = diversity_time_gap
|
|
1308
1334
|
|
|
1309
1335
|
if use_diversity_discr:
|
|
1310
|
-
assert exists(latent_gene_pool), 'latent_gene_pool must be present to use DIAYN'
|
|
1336
|
+
assert exists(latent_gene_pool), 'latent_gene_pool must be present to use DIAYN / DADS'
|
|
1311
1337
|
dim_state = actor.init_layer[0].in_features
|
|
1312
1338
|
|
|
1313
1339
|
self.diversity_discr = DiversityDiscr(
|
|
1314
1340
|
dim_state = dim_state,
|
|
1315
1341
|
num_latents = latent_gene_pool.num_latents,
|
|
1342
|
+
time_gap = diversity_time_gap,
|
|
1316
1343
|
**diversity_discr_kwargs
|
|
1317
1344
|
)
|
|
1318
1345
|
|
|
@@ -1443,6 +1470,7 @@ class Agent(Module):
|
|
|
1443
1470
|
critic_ema = self.critic_ema.state_dict() if self.use_critic_ema else None,
|
|
1444
1471
|
latents = unwrap(self.latent_gene_pool).state_dict() if self.has_latent_genes else None,
|
|
1445
1472
|
diversity_discr = unwrap(self.diversity_discr).state_dict() if self.use_diversity_discr else None,
|
|
1473
|
+
diversity_time_gap = self.diversity_time_gap,
|
|
1446
1474
|
has_diversity_discr_warmed_up = self.has_diversity_discr_warmed_up.item(),
|
|
1447
1475
|
actor_optim = unwrap_optim(self.actor_optim).state_dict(),
|
|
1448
1476
|
critic_optim = unwrap_optim(self.critic_optim).state_dict(),
|
|
@@ -1475,6 +1503,9 @@ class Agent(Module):
|
|
|
1475
1503
|
if self.use_diversity_discr and 'diversity_discr' in pkg and exists(pkg['diversity_discr']):
|
|
1476
1504
|
unwrap(self.diversity_discr).load_state_dict(pkg['diversity_discr'])
|
|
1477
1505
|
|
|
1506
|
+
if 'diversity_time_gap' in pkg:
|
|
1507
|
+
self.diversity_time_gap = pkg['diversity_time_gap']
|
|
1508
|
+
|
|
1478
1509
|
if 'has_diversity_discr_warmed_up' in pkg:
|
|
1479
1510
|
self.has_diversity_discr_warmed_up.copy_(tensor(pkg['has_diversity_discr_warmed_up']))
|
|
1480
1511
|
|
|
@@ -1577,13 +1608,12 @@ class Agent(Module):
|
|
|
1577
1608
|
epochs = 2
|
|
1578
1609
|
|
|
1579
1610
|
):
|
|
1580
|
-
memories_and_cumulative_rewards = to_device(memories_and_cumulative_rewards, self.device)
|
|
1581
|
-
|
|
1582
1611
|
memories_list, rewards_per_latent_episode = memories_and_cumulative_rewards
|
|
1583
1612
|
|
|
1584
|
-
# stack
|
|
1613
|
+
# stack, then move once per field
|
|
1585
1614
|
|
|
1586
|
-
memories = map(stack, zip(*memories_list))
|
|
1615
|
+
memories = [t.to(self.device) for t in map(stack, zip(*memories_list))]
|
|
1616
|
+
rewards_per_latent_episode = rewards_per_latent_episode.to(self.device)
|
|
1587
1617
|
|
|
1588
1618
|
memories_list.clear()
|
|
1589
1619
|
|
|
@@ -1625,12 +1655,15 @@ class Agent(Module):
|
|
|
1625
1655
|
|
|
1626
1656
|
valid_episode = episode_ids >= 0
|
|
1627
1657
|
|
|
1628
|
-
|
|
1658
|
+
fields = tuple(t[valid_episode] for t in (advantages, states, next_states, latent_gene_ids, actions, log_probs, values, dones))
|
|
1629
1659
|
|
|
1630
|
-
|
|
1660
|
+
if self.wrap_with_accelerate or self.use_dataloader:
|
|
1661
|
+
dataloader = DataLoader(TensorDataset(*fields), batch_size = self.batch_size, shuffle = True)
|
|
1631
1662
|
|
|
1632
|
-
|
|
1633
|
-
|
|
1663
|
+
if self.wrap_with_accelerate:
|
|
1664
|
+
dataloader = self.accelerate.prepare(dataloader)
|
|
1665
|
+
else:
|
|
1666
|
+
dataloader = ShuffledBatches(fields, self.batch_size)
|
|
1634
1667
|
|
|
1635
1668
|
# updating actor and critic
|
|
1636
1669
|
|
|
@@ -1722,7 +1755,8 @@ class Agent(Module):
|
|
|
1722
1755
|
diversity_discr_loss = self.zero
|
|
1723
1756
|
|
|
1724
1757
|
if self.use_diversity_discr:
|
|
1725
|
-
|
|
1758
|
+
discr_inp = (states,) if self.diversity_time_gap == 0 else (states, next_states)
|
|
1759
|
+
diversity_discr_logits = self.diversity_discr(*discr_inp)
|
|
1726
1760
|
diversity_discr_loss = F.cross_entropy(diversity_discr_logits, latent_gene_ids)
|
|
1727
1761
|
|
|
1728
1762
|
diversity_discr_loss.backward()
|
|
@@ -1878,6 +1912,7 @@ def create_agent(
|
|
|
1878
1912
|
use_critic_ema = True,
|
|
1879
1913
|
use_state_norm = False,
|
|
1880
1914
|
action_is_continuous = False, # continuous control - beta policy
|
|
1915
|
+
diversity_time_gap = 1,
|
|
1881
1916
|
latent_gene_pool_kwargs: dict = dict(),
|
|
1882
1917
|
actor_kwargs: dict = dict(),
|
|
1883
1918
|
critic_kwargs: dict = dict(),
|
|
@@ -1923,6 +1958,7 @@ def create_agent(
|
|
|
1923
1958
|
state_norm = state_norm,
|
|
1924
1959
|
latent_gene_pool = latent_gene_pool,
|
|
1925
1960
|
use_critic_ema = use_critic_ema,
|
|
1961
|
+
diversity_time_gap = diversity_time_gap,
|
|
1926
1962
|
**kwargs
|
|
1927
1963
|
)
|
|
1928
1964
|
|
|
@@ -2142,6 +2178,7 @@ class EPO(Module):
|
|
|
2142
2178
|
|
|
2143
2179
|
next_obs, rewards, terminated, truncated = env.step_batch(actions.cpu().numpy(), worker_ids = active)[:4]
|
|
2144
2180
|
|
|
2181
|
+
next_states = from_numpy(np.ascontiguousarray(next_obs)).float().to(self.device)
|
|
2145
2182
|
rewards = from_numpy(np.asarray(rewards)).float().to(self.device)
|
|
2146
2183
|
terminated = from_numpy(np.asarray(terminated)).to(self.device)
|
|
2147
2184
|
truncated = from_numpy(np.asarray(truncated)).to(self.device)
|
|
@@ -2151,7 +2188,7 @@ class EPO(Module):
|
|
|
2151
2188
|
|
|
2152
2189
|
latent_id, episode_id, latent, state = slot.latent_id, slot.episode_id, slot.latent, slot.state
|
|
2153
2190
|
|
|
2154
|
-
next_state =
|
|
2191
|
+
next_state = next_states[k]
|
|
2155
2192
|
|
|
2156
2193
|
reward, terminated_at, truncated_at = rewards[k], terminated[k], truncated[k]
|
|
2157
2194
|
|
|
@@ -2159,7 +2196,16 @@ class EPO(Module):
|
|
|
2159
2196
|
|
|
2160
2197
|
if self.agent.use_diversity_discr and self.agent.has_diversity_discr_warmed_up.item():
|
|
2161
2198
|
with torch.no_grad():
|
|
2162
|
-
|
|
2199
|
+
discr = self.agent.unwrap_model(self.agent.diversity_discr)
|
|
2200
|
+
time_gap = self.agent.diversity_time_gap
|
|
2201
|
+
|
|
2202
|
+
if time_gap == 0:
|
|
2203
|
+
logits = discr(rearrange(state, '... -> 1 ...'))
|
|
2204
|
+
elif time_gap == 1 or len(slot.memories) < (time_gap - 1):
|
|
2205
|
+
logits = discr(rearrange(state, '... -> 1 ...'), rearrange(next_state, '... -> 1 ...'))
|
|
2206
|
+
else:
|
|
2207
|
+
past_state = slot.memories[-(time_gap - 1)].state
|
|
2208
|
+
logits = discr(rearrange(past_state, '... -> 1 ...'), rearrange(next_state, '... -> 1 ...'))
|
|
2163
2209
|
|
|
2164
2210
|
latent_log_probs = logits.log_softmax(dim = -1)
|
|
2165
2211
|
diversity_reward = latent_log_probs[0, latent_id] + math.log(self.agent.num_latents)
|
|
@@ -2184,6 +2230,11 @@ class EPO(Module):
|
|
|
2184
2230
|
|
|
2185
2231
|
slot.memories.append(memory)
|
|
2186
2232
|
|
|
2233
|
+
if self.agent.use_diversity_discr and self.agent.diversity_time_gap > 1:
|
|
2234
|
+
time_gap = self.agent.diversity_time_gap
|
|
2235
|
+
if len(slot.memories) >= time_gap:
|
|
2236
|
+
slot.memories[-time_gap] = slot.memories[-time_gap]._replace(next_state = next_state)
|
|
2237
|
+
|
|
2187
2238
|
rewards_per_latent_episode[latent_id, episode_id] += reward
|
|
2188
2239
|
|
|
2189
2240
|
# episode is done - bootstrap value if truncated, then refill
|
{evolutionary_policy_optimization-0.3.5 → evolutionary_policy_optimization-0.4.1}/pyproject.toml
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "evolutionary-policy-optimization"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.4.1"
|
|
4
4
|
description = "EPO - Pytorch"
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Phil Wang", email = "lucidrains@gmail.com" }
|
|
@@ -30,7 +30,7 @@ dependencies = [
|
|
|
30
30
|
'einops>=0.8.1',
|
|
31
31
|
'ema-pytorch>=0.7.7',
|
|
32
32
|
'hl-gauss-pytorch>=0.2.8',
|
|
33
|
-
'mean-conc-beta>=0.
|
|
33
|
+
'mean-conc-beta>=0.2.7',
|
|
34
34
|
'torch>=2.2',
|
|
35
35
|
'tqdm',
|
|
36
36
|
"x-mlps-pytorch>=0.3.0",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|