evolutionary-policy-optimization 0.3.5__tar.gz → 0.4.0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: evolutionary-policy-optimization
3
- Version: 0.3.5
3
+ Version: 0.4.0
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
@@ -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
@@ -513,7 +513,7 @@ class MLP(Module):
513
513
 
514
514
  return self.final_lime(x, prev_layer_inputs)
515
515
 
516
- # discriminator for predicting latent code from states and actions (DIAYN - Eysenbach et al. 2018)
516
+ # discriminator for predicting latent code from states or state transitions (DIAYN / DADS)
517
517
 
518
518
  class DiversityDiscr(Module):
519
519
  def __init__(
@@ -521,15 +521,19 @@ class DiversityDiscr(Module):
521
521
  dim_state,
522
522
  num_latents,
523
523
  dim = 64,
524
- depth = 2
524
+ depth = 2,
525
+ time_gap = 1
525
526
  ):
526
527
  super().__init__()
528
+ self.time_gap = time_gap
529
+ self.state_transition = time_gap > 0
530
+
527
531
  self.state_proj = nn.Linear(dim_state, dim)
528
532
 
529
533
  self.net = AttnResidualNormedMLP(
530
534
  dim = dim,
531
535
  depth = depth,
532
- dim_in = dim * 2,
536
+ dim_in = dim * 2 if self.state_transition else dim,
533
537
  dim_out = num_latents
534
538
  )
535
539
 
@@ -538,8 +542,12 @@ class DiversityDiscr(Module):
538
542
  if isinstance(module, (nn.Linear, nn.LayerNorm, nn.RMSNorm)):
539
543
  module.reset_parameters()
540
544
 
541
- def forward(self, state, next_state):
545
+ def forward(self, state, next_state = None):
542
546
  state_embed = self.state_proj(state)
547
+
548
+ if not self.state_transition or not exists(next_state):
549
+ return self.net(state_embed)
550
+
543
551
  next_state_embed = self.state_proj(next_state)
544
552
  return self.net((state_embed, next_state_embed))
545
553
 
@@ -1215,6 +1223,7 @@ class Agent(Module):
1215
1223
  critic_optim_kwargs: dict = dict(),
1216
1224
  latent_optim_kwargs: dict = dict(),
1217
1225
  use_diversity_discr = False,
1226
+ diversity_time_gap = 1, # 0 for DIAYN (state only), >= 1 for DADS (state transition with given time gap)
1218
1227
  diversity_discr_kwargs: dict = dict(dim = 64, depth = 2),
1219
1228
  diversity_discr_lr = 3e-4,
1220
1229
  diversity_discr_optim_kwargs: dict = dict(),
@@ -1305,14 +1314,16 @@ class Agent(Module):
1305
1314
  # diversity discriminator
1306
1315
 
1307
1316
  self.use_diversity_discr = use_diversity_discr
1317
+ self.diversity_time_gap = diversity_time_gap
1308
1318
 
1309
1319
  if use_diversity_discr:
1310
- assert exists(latent_gene_pool), 'latent_gene_pool must be present to use DIAYN'
1320
+ assert exists(latent_gene_pool), 'latent_gene_pool must be present to use DIAYN / DADS'
1311
1321
  dim_state = actor.init_layer[0].in_features
1312
1322
 
1313
1323
  self.diversity_discr = DiversityDiscr(
1314
1324
  dim_state = dim_state,
1315
1325
  num_latents = latent_gene_pool.num_latents,
1326
+ time_gap = diversity_time_gap,
1316
1327
  **diversity_discr_kwargs
1317
1328
  )
1318
1329
 
@@ -1443,6 +1454,7 @@ class Agent(Module):
1443
1454
  critic_ema = self.critic_ema.state_dict() if self.use_critic_ema else None,
1444
1455
  latents = unwrap(self.latent_gene_pool).state_dict() if self.has_latent_genes else None,
1445
1456
  diversity_discr = unwrap(self.diversity_discr).state_dict() if self.use_diversity_discr else None,
1457
+ diversity_time_gap = self.diversity_time_gap,
1446
1458
  has_diversity_discr_warmed_up = self.has_diversity_discr_warmed_up.item(),
1447
1459
  actor_optim = unwrap_optim(self.actor_optim).state_dict(),
1448
1460
  critic_optim = unwrap_optim(self.critic_optim).state_dict(),
@@ -1475,6 +1487,9 @@ class Agent(Module):
1475
1487
  if self.use_diversity_discr and 'diversity_discr' in pkg and exists(pkg['diversity_discr']):
1476
1488
  unwrap(self.diversity_discr).load_state_dict(pkg['diversity_discr'])
1477
1489
 
1490
+ if 'diversity_time_gap' in pkg:
1491
+ self.diversity_time_gap = pkg['diversity_time_gap']
1492
+
1478
1493
  if 'has_diversity_discr_warmed_up' in pkg:
1479
1494
  self.has_diversity_discr_warmed_up.copy_(tensor(pkg['has_diversity_discr_warmed_up']))
1480
1495
 
@@ -1722,7 +1737,8 @@ class Agent(Module):
1722
1737
  diversity_discr_loss = self.zero
1723
1738
 
1724
1739
  if self.use_diversity_discr:
1725
- diversity_discr_logits = self.diversity_discr(states, next_states)
1740
+ discr_inp = (states,) if self.diversity_time_gap == 0 else (states, next_states)
1741
+ diversity_discr_logits = self.diversity_discr(*discr_inp)
1726
1742
  diversity_discr_loss = F.cross_entropy(diversity_discr_logits, latent_gene_ids)
1727
1743
 
1728
1744
  diversity_discr_loss.backward()
@@ -1878,6 +1894,7 @@ def create_agent(
1878
1894
  use_critic_ema = True,
1879
1895
  use_state_norm = False,
1880
1896
  action_is_continuous = False, # continuous control - beta policy
1897
+ diversity_time_gap = 1,
1881
1898
  latent_gene_pool_kwargs: dict = dict(),
1882
1899
  actor_kwargs: dict = dict(),
1883
1900
  critic_kwargs: dict = dict(),
@@ -1923,6 +1940,7 @@ def create_agent(
1923
1940
  state_norm = state_norm,
1924
1941
  latent_gene_pool = latent_gene_pool,
1925
1942
  use_critic_ema = use_critic_ema,
1943
+ diversity_time_gap = diversity_time_gap,
1926
1944
  **kwargs
1927
1945
  )
1928
1946
 
@@ -2159,7 +2177,16 @@ class EPO(Module):
2159
2177
 
2160
2178
  if self.agent.use_diversity_discr and self.agent.has_diversity_discr_warmed_up.item():
2161
2179
  with torch.no_grad():
2162
- logits = self.agent.unwrap_model(self.agent.diversity_discr)(rearrange(state, '... -> 1 ...'), rearrange(next_state, '... -> 1 ...'))
2180
+ discr = self.agent.unwrap_model(self.agent.diversity_discr)
2181
+ time_gap = self.agent.diversity_time_gap
2182
+
2183
+ if time_gap == 0:
2184
+ logits = discr(rearrange(state, '... -> 1 ...'))
2185
+ elif time_gap == 1 or len(slot.memories) < (time_gap - 1):
2186
+ logits = discr(rearrange(state, '... -> 1 ...'), rearrange(next_state, '... -> 1 ...'))
2187
+ else:
2188
+ past_state = slot.memories[-(time_gap - 1)].state
2189
+ logits = discr(rearrange(past_state, '... -> 1 ...'), rearrange(next_state, '... -> 1 ...'))
2163
2190
 
2164
2191
  latent_log_probs = logits.log_softmax(dim = -1)
2165
2192
  diversity_reward = latent_log_probs[0, latent_id] + math.log(self.agent.num_latents)
@@ -2184,6 +2211,11 @@ class EPO(Module):
2184
2211
 
2185
2212
  slot.memories.append(memory)
2186
2213
 
2214
+ if self.agent.use_diversity_discr and self.agent.diversity_time_gap > 1:
2215
+ time_gap = self.agent.diversity_time_gap
2216
+ if len(slot.memories) >= time_gap:
2217
+ slot.memories[-time_gap] = slot.memories[-time_gap]._replace(next_state = next_state)
2218
+
2187
2219
  rewards_per_latent_episode[latent_id, episode_id] += reward
2188
2220
 
2189
2221
  # episode is done - bootstrap value if truncated, then refill
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "evolutionary-policy-optimization"
3
- version = "0.3.5"
3
+ version = "0.4.0"
4
4
  description = "EPO - Pytorch"
5
5
  authors = [
6
6
  { name = "Phil Wang", email = "lucidrains@gmail.com" }