evolutionary-policy-optimization 0.2.16__tar.gz → 0.2.19__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.2.16 → evolutionary_policy_optimization-0.2.19}/PKG-INFO +55 -3
- {evolutionary_policy_optimization-0.2.16 → evolutionary_policy_optimization-0.2.19}/README.md +53 -2
- {evolutionary_policy_optimization-0.2.16 → evolutionary_policy_optimization-0.2.19}/evolutionary_policy_optimization/epo.py +154 -16
- {evolutionary_policy_optimization-0.2.16 → evolutionary_policy_optimization-0.2.19}/evolutionary_policy_optimization/experimental.py +12 -5
- {evolutionary_policy_optimization-0.2.16 → evolutionary_policy_optimization-0.2.19}/pyproject.toml +3 -2
- {evolutionary_policy_optimization-0.2.16 → evolutionary_policy_optimization-0.2.19}/.gitignore +0 -0
- {evolutionary_policy_optimization-0.2.16 → evolutionary_policy_optimization-0.2.19}/LICENSE +0 -0
- {evolutionary_policy_optimization-0.2.16 → evolutionary_policy_optimization-0.2.19}/evolutionary_policy_optimization/__init__.py +0 -0
- {evolutionary_policy_optimization-0.2.16 → evolutionary_policy_optimization-0.2.19}/evolutionary_policy_optimization/distributed.py +0 -0
- {evolutionary_policy_optimization-0.2.16 → evolutionary_policy_optimization-0.2.19}/evolutionary_policy_optimization/env_wrappers.py +0 -0
- {evolutionary_policy_optimization-0.2.16 → evolutionary_policy_optimization-0.2.19}/evolutionary_policy_optimization/mock_env.py +0 -0
{evolutionary_policy_optimization-0.2.16 → evolutionary_policy_optimization-0.2.19}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: evolutionary-policy-optimization
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.19
|
|
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
|
|
@@ -43,6 +43,7 @@ Requires-Dist: ema-pytorch>=0.7.7
|
|
|
43
43
|
Requires-Dist: hl-gauss-pytorch>=0.1.19
|
|
44
44
|
Requires-Dist: torch>=2.2
|
|
45
45
|
Requires-Dist: tqdm
|
|
46
|
+
Requires-Dist: x-mlps-pytorch>=0.3.0
|
|
46
47
|
Provides-Extra: examples
|
|
47
48
|
Requires-Dist: numpy; extra == 'examples'
|
|
48
49
|
Requires-Dist: pufferlib>=2.0.6; extra == 'examples'
|
|
@@ -302,13 +303,13 @@ That's it
|
|
|
302
303
|
|
|
303
304
|
```bibtex
|
|
304
305
|
@misc{xie2025simplepolicyoptimization,
|
|
305
|
-
title = {Simple Policy Optimization},
|
|
306
|
+
title = {Simple Policy Optimization},
|
|
306
307
|
author = {Zhengpeng Xie and Qiang Zhang and Fan Yang and Marco Hutter and Renjing Xu},
|
|
307
308
|
year = {2025},
|
|
308
309
|
eprint = {2401.16025},
|
|
309
310
|
archivePrefix = {arXiv},
|
|
310
311
|
primaryClass = {cs.LG},
|
|
311
|
-
url = {https://arxiv.org/abs/2401.16025},
|
|
312
|
+
url = {https://arxiv.org/abs/2401.16025},
|
|
312
313
|
}
|
|
313
314
|
```
|
|
314
315
|
|
|
@@ -322,6 +323,57 @@ That's it
|
|
|
322
323
|
}
|
|
323
324
|
```
|
|
324
325
|
|
|
326
|
+
```bibtex
|
|
327
|
+
@article{Zhu2025Hybrid,
|
|
328
|
+
author = {Zhu, Zimo and Yu, Chuanqiang and Wang, Junti},
|
|
329
|
+
title = {A Hybrid Genetic Algorithm and Proximal Policy Optimization System for Efficient Multi-Agent Task Allocation},
|
|
330
|
+
journal = {Systems},
|
|
331
|
+
volume = {13},
|
|
332
|
+
year = {2025},
|
|
333
|
+
number = {6},
|
|
334
|
+
article-number = {453},
|
|
335
|
+
url = {https://www.mdpi.com/2079-8954/13/6/453},
|
|
336
|
+
issn = {2079-8954}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
```bibtex
|
|
340
|
+
@misc{kedia2026simtoolrealobjectcentricpolicyzeroshot,
|
|
341
|
+
title = {SimToolReal: An Object-Centric Policy for Zero-Shot Dexterous Tool Manipulation},
|
|
342
|
+
@misc{kedia2026simtoolrealobjectcentricpolicyzeroshot,
|
|
343
|
+
title = {SimToolReal: An Object-Centric Policy for Zero-Shot Dexterous Tool Manipulation},
|
|
344
|
+
author = {Kushal Kedia and Tyler Ga Wei Lum and Jeannette Bohg and C. Karen Liu},
|
|
345
|
+
year = {2026},
|
|
346
|
+
eprint = {2602.16863},
|
|
347
|
+
archivePrefix = {arXiv},
|
|
348
|
+
primaryClass = {cs.RO},
|
|
349
|
+
url = {https://arxiv.org/abs/2602.16863},
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
```bibtex
|
|
354
|
+
@article{Eysenbach2018DiversityIA,
|
|
355
|
+
title = {Diversity is All You Need: Learning Skills without a Reward Function},
|
|
356
|
+
author = {Benjamin Eysenbach and Abhishek Gupta and Julian Ibarz and Sergey Levine},
|
|
357
|
+
journal = {ArXiv},
|
|
358
|
+
year = {2018},
|
|
359
|
+
volume = {abs/1802.06070},
|
|
360
|
+
url = {https://arxiv.org/abs/1802.06070}
|
|
361
|
+
url = {https://arxiv.org/abs/2602.16863},
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
```bibtex
|
|
365
|
+
@article{Zhu2025Hybrid,
|
|
366
|
+
author = {Zhu, Zimo and Yu, Chuanqiang and Wang, Junti},
|
|
367
|
+
title = {A Hybrid Genetic Algorithm and Proximal Policy Optimization System for Efficient Multi-Agent Task Allocation},
|
|
368
|
+
journal = {Systems},
|
|
369
|
+
volume = {13},
|
|
370
|
+
year = {2025},
|
|
371
|
+
number = {6},
|
|
372
|
+
article-number = {453},
|
|
373
|
+
url = {https://www.mdpi.com/2079-8954/13/6/453},
|
|
374
|
+
issn = {2079-8954}
|
|
375
|
+
```
|
|
376
|
+
|
|
325
377
|
```bibtex
|
|
326
378
|
@misc{kedia2026simtoolrealobjectcentricpolicyzeroshot,
|
|
327
379
|
title = {SimToolReal: An Object-Centric Policy for Zero-Shot Dexterous Tool Manipulation},
|
{evolutionary_policy_optimization-0.2.16 → evolutionary_policy_optimization-0.2.19}/README.md
RENAMED
|
@@ -245,13 +245,13 @@ That's it
|
|
|
245
245
|
|
|
246
246
|
```bibtex
|
|
247
247
|
@misc{xie2025simplepolicyoptimization,
|
|
248
|
-
title = {Simple Policy Optimization},
|
|
248
|
+
title = {Simple Policy Optimization},
|
|
249
249
|
author = {Zhengpeng Xie and Qiang Zhang and Fan Yang and Marco Hutter and Renjing Xu},
|
|
250
250
|
year = {2025},
|
|
251
251
|
eprint = {2401.16025},
|
|
252
252
|
archivePrefix = {arXiv},
|
|
253
253
|
primaryClass = {cs.LG},
|
|
254
|
-
url = {https://arxiv.org/abs/2401.16025},
|
|
254
|
+
url = {https://arxiv.org/abs/2401.16025},
|
|
255
255
|
}
|
|
256
256
|
```
|
|
257
257
|
|
|
@@ -265,6 +265,57 @@ That's it
|
|
|
265
265
|
}
|
|
266
266
|
```
|
|
267
267
|
|
|
268
|
+
```bibtex
|
|
269
|
+
@article{Zhu2025Hybrid,
|
|
270
|
+
author = {Zhu, Zimo and Yu, Chuanqiang and Wang, Junti},
|
|
271
|
+
title = {A Hybrid Genetic Algorithm and Proximal Policy Optimization System for Efficient Multi-Agent Task Allocation},
|
|
272
|
+
journal = {Systems},
|
|
273
|
+
volume = {13},
|
|
274
|
+
year = {2025},
|
|
275
|
+
number = {6},
|
|
276
|
+
article-number = {453},
|
|
277
|
+
url = {https://www.mdpi.com/2079-8954/13/6/453},
|
|
278
|
+
issn = {2079-8954}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
```bibtex
|
|
282
|
+
@misc{kedia2026simtoolrealobjectcentricpolicyzeroshot,
|
|
283
|
+
title = {SimToolReal: An Object-Centric Policy for Zero-Shot Dexterous Tool Manipulation},
|
|
284
|
+
@misc{kedia2026simtoolrealobjectcentricpolicyzeroshot,
|
|
285
|
+
title = {SimToolReal: An Object-Centric Policy for Zero-Shot Dexterous Tool Manipulation},
|
|
286
|
+
author = {Kushal Kedia and Tyler Ga Wei Lum and Jeannette Bohg and C. Karen Liu},
|
|
287
|
+
year = {2026},
|
|
288
|
+
eprint = {2602.16863},
|
|
289
|
+
archivePrefix = {arXiv},
|
|
290
|
+
primaryClass = {cs.RO},
|
|
291
|
+
url = {https://arxiv.org/abs/2602.16863},
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
```bibtex
|
|
296
|
+
@article{Eysenbach2018DiversityIA,
|
|
297
|
+
title = {Diversity is All You Need: Learning Skills without a Reward Function},
|
|
298
|
+
author = {Benjamin Eysenbach and Abhishek Gupta and Julian Ibarz and Sergey Levine},
|
|
299
|
+
journal = {ArXiv},
|
|
300
|
+
year = {2018},
|
|
301
|
+
volume = {abs/1802.06070},
|
|
302
|
+
url = {https://arxiv.org/abs/1802.06070}
|
|
303
|
+
url = {https://arxiv.org/abs/2602.16863},
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
```bibtex
|
|
307
|
+
@article{Zhu2025Hybrid,
|
|
308
|
+
author = {Zhu, Zimo and Yu, Chuanqiang and Wang, Junti},
|
|
309
|
+
title = {A Hybrid Genetic Algorithm and Proximal Policy Optimization System for Efficient Multi-Agent Task Allocation},
|
|
310
|
+
journal = {Systems},
|
|
311
|
+
volume = {13},
|
|
312
|
+
year = {2025},
|
|
313
|
+
number = {6},
|
|
314
|
+
article-number = {453},
|
|
315
|
+
url = {https://www.mdpi.com/2079-8954/13/6/453},
|
|
316
|
+
issn = {2079-8954}
|
|
317
|
+
```
|
|
318
|
+
|
|
268
319
|
```bibtex
|
|
269
320
|
@misc{kedia2026simtoolrealobjectcentricpolicyzeroshot,
|
|
270
321
|
title = {SimToolReal: An Object-Centric Policy for Zero-Shot Dexterous Tool Manipulation},
|
|
@@ -22,6 +22,8 @@ import einx
|
|
|
22
22
|
from einops import rearrange, repeat, reduce, einsum, pack
|
|
23
23
|
from einops.layers.torch import Rearrange
|
|
24
24
|
|
|
25
|
+
from x_mlps_pytorch import AttnResidualNormedMLP
|
|
26
|
+
|
|
25
27
|
from evolutionary_policy_optimization.distributed import (
|
|
26
28
|
is_distributed,
|
|
27
29
|
get_world_and_rank,
|
|
@@ -532,6 +534,38 @@ class MLP(Module):
|
|
|
532
534
|
|
|
533
535
|
return self.final_lime(x, prev_layer_inputs)
|
|
534
536
|
|
|
537
|
+
# discriminator for predicting latent code from states and actions (DIAYN - Eysenbach et al. 2018)
|
|
538
|
+
|
|
539
|
+
class DiversityDiscr(Module):
|
|
540
|
+
def __init__(
|
|
541
|
+
self,
|
|
542
|
+
dim_state,
|
|
543
|
+
num_actions,
|
|
544
|
+
num_latents,
|
|
545
|
+
dim = 64,
|
|
546
|
+
depth = 2
|
|
547
|
+
):
|
|
548
|
+
super().__init__()
|
|
549
|
+
self.action_embed = nn.Embedding(num_actions, dim)
|
|
550
|
+
self.state_proj = nn.Linear(dim_state, dim)
|
|
551
|
+
|
|
552
|
+
self.net = AttnResidualNormedMLP(
|
|
553
|
+
dim = dim,
|
|
554
|
+
depth = depth,
|
|
555
|
+
dim_in = dim * 2,
|
|
556
|
+
dim_out = num_latents
|
|
557
|
+
)
|
|
558
|
+
|
|
559
|
+
def reset_parameters(self):
|
|
560
|
+
for module in self.modules():
|
|
561
|
+
if isinstance(module, (nn.Linear, nn.LayerNorm, nn.RMSNorm, nn.Embedding)):
|
|
562
|
+
module.reset_parameters()
|
|
563
|
+
|
|
564
|
+
def forward(self, state, action):
|
|
565
|
+
state_embed = self.state_proj(state)
|
|
566
|
+
action_embed = self.action_embed(action)
|
|
567
|
+
return self.net((state_embed, action_embed))
|
|
568
|
+
|
|
535
569
|
# actor, critic, and agent (actor + critic)
|
|
536
570
|
# eventually, should just create a separate repo and aggregate all the MLP related architectures
|
|
537
571
|
|
|
@@ -862,7 +896,11 @@ class LatentGenePool(Module):
|
|
|
862
896
|
|
|
863
897
|
if not divisible_by(self.step.item(), self.apply_genetic_algorithm_every):
|
|
864
898
|
self.advance_step_()
|
|
865
|
-
|
|
899
|
+
|
|
900
|
+
if inplace:
|
|
901
|
+
return False, None
|
|
902
|
+
|
|
903
|
+
return False, self.latents
|
|
866
904
|
|
|
867
905
|
"""
|
|
868
906
|
i - islands
|
|
@@ -894,9 +932,9 @@ class LatentGenePool(Module):
|
|
|
894
932
|
|
|
895
933
|
if not should_update_per_island.any():
|
|
896
934
|
if inplace:
|
|
897
|
-
return
|
|
935
|
+
return False, None
|
|
898
936
|
|
|
899
|
-
return genes
|
|
937
|
+
return False, genes
|
|
900
938
|
|
|
901
939
|
genes = rearrange(genes, '(i p) ... -> i p ...', i = islands)
|
|
902
940
|
|
|
@@ -982,8 +1020,10 @@ class LatentGenePool(Module):
|
|
|
982
1020
|
|
|
983
1021
|
genes = rearrange(genes, 'i p ... -> (i p) ...')
|
|
984
1022
|
|
|
1023
|
+
ret = (True, genes)
|
|
1024
|
+
|
|
985
1025
|
if not inplace:
|
|
986
|
-
return
|
|
1026
|
+
return ret
|
|
987
1027
|
|
|
988
1028
|
# store the genes for the next interaction with environment for new fitness values (a function of reward and other to be researched measures)
|
|
989
1029
|
|
|
@@ -991,6 +1031,9 @@ class LatentGenePool(Module):
|
|
|
991
1031
|
|
|
992
1032
|
self.advance_step_()
|
|
993
1033
|
|
|
1034
|
+
if inplace:
|
|
1035
|
+
return ret
|
|
1036
|
+
|
|
994
1037
|
def forward(
|
|
995
1038
|
self,
|
|
996
1039
|
latent_id: int | None = None,
|
|
@@ -1071,6 +1114,10 @@ class Agent(Module):
|
|
|
1071
1114
|
actor_optim_kwargs: dict = dict(),
|
|
1072
1115
|
critic_optim_kwargs: dict = dict(),
|
|
1073
1116
|
latent_optim_kwargs: dict = dict(),
|
|
1117
|
+
use_diversity_discr = False,
|
|
1118
|
+
diversity_discr_kwargs: dict = dict(dim = 64, depth = 2),
|
|
1119
|
+
diversity_discr_lr = 3e-4,
|
|
1120
|
+
diversity_discr_optim_kwargs: dict = dict(),
|
|
1074
1121
|
get_fitness_scores: Callable[..., Tensor] = get_fitness_scores,
|
|
1075
1122
|
wrap_with_accelerate: bool = True,
|
|
1076
1123
|
accelerate_kwargs: dict = dict(),
|
|
@@ -1147,6 +1194,30 @@ class Agent(Module):
|
|
|
1147
1194
|
|
|
1148
1195
|
self.latent_optim = optim_klass(latent_gene_pool.parameters(), lr = latent_lr, **latent_optim_kwargs) if exists(latent_gene_pool) and not latent_gene_pool.frozen_latents else None
|
|
1149
1196
|
|
|
1197
|
+
# diversity discriminator
|
|
1198
|
+
|
|
1199
|
+
self.use_diversity_discr = use_diversity_discr
|
|
1200
|
+
|
|
1201
|
+
if use_diversity_discr:
|
|
1202
|
+
assert exists(latent_gene_pool), 'latent_gene_pool must be present to use DIAYN'
|
|
1203
|
+
dim_state = actor.init_layer[0].in_features
|
|
1204
|
+
num_actions = actor.to_out[1].out_features
|
|
1205
|
+
|
|
1206
|
+
self.diversity_discr = DiversityDiscr(
|
|
1207
|
+
dim_state = dim_state,
|
|
1208
|
+
num_actions = num_actions,
|
|
1209
|
+
num_latents = latent_gene_pool.num_latents,
|
|
1210
|
+
**diversity_discr_kwargs
|
|
1211
|
+
)
|
|
1212
|
+
|
|
1213
|
+
self.diversity_discr_optim = optim_klass(self.diversity_discr.parameters(), lr = diversity_discr_lr, **diversity_discr_optim_kwargs)
|
|
1214
|
+
else:
|
|
1215
|
+
self.diversity_discr = None
|
|
1216
|
+
self.diversity_discr_optim = None
|
|
1217
|
+
|
|
1218
|
+
self.register_buffer('has_diversity_discr_warmed_up', tensor(False))
|
|
1219
|
+
self.register_buffer('zero', tensor(0.))
|
|
1220
|
+
|
|
1150
1221
|
# shrink and perturb every
|
|
1151
1222
|
|
|
1152
1223
|
self.should_noise_weights = exists(shrink_and_perturb_every)
|
|
@@ -1174,18 +1245,22 @@ class Agent(Module):
|
|
|
1174
1245
|
self.actor,
|
|
1175
1246
|
self.critic,
|
|
1176
1247
|
self.latent_gene_pool,
|
|
1248
|
+
self.diversity_discr,
|
|
1177
1249
|
self.actor_optim,
|
|
1178
1250
|
self.critic_optim,
|
|
1179
1251
|
self.latent_optim,
|
|
1252
|
+
self.diversity_discr_optim,
|
|
1180
1253
|
) = tuple(
|
|
1181
1254
|
maybe(self.accelerate.prepare)(m) for m in (
|
|
1182
1255
|
self.state_norm,
|
|
1183
1256
|
self.actor,
|
|
1184
1257
|
self.critic,
|
|
1185
1258
|
self.latent_gene_pool,
|
|
1259
|
+
self.diversity_discr,
|
|
1186
1260
|
self.actor_optim,
|
|
1187
1261
|
self.critic_optim,
|
|
1188
1262
|
self.latent_optim,
|
|
1263
|
+
self.diversity_discr_optim,
|
|
1189
1264
|
)
|
|
1190
1265
|
)
|
|
1191
1266
|
|
|
@@ -1215,24 +1290,28 @@ class Agent(Module):
|
|
|
1215
1290
|
def save(self, path, overwrite = False):
|
|
1216
1291
|
path = Path(path)
|
|
1217
1292
|
unwrap = self.unwrap_model
|
|
1293
|
+
unwrap_optim = lambda opt: opt.optimizer if hasattr(opt, 'optimizer') else opt
|
|
1218
1294
|
|
|
1219
1295
|
assert not path.exists() or overwrite
|
|
1220
1296
|
|
|
1221
1297
|
pkg = dict(
|
|
1222
|
-
state_norm = unwrap(self.state_norm).state_dict() if self.state_norm else None,
|
|
1223
1298
|
actor = unwrap(self.actor).state_dict(),
|
|
1224
1299
|
critic = unwrap(self.critic).state_dict(),
|
|
1225
1300
|
critic_ema = self.critic_ema.state_dict() if self.use_critic_ema else None,
|
|
1226
1301
|
latents = unwrap(self.latent_gene_pool).state_dict() if self.has_latent_genes else None,
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1302
|
+
diversity_discr = unwrap(self.diversity_discr).state_dict() if self.use_diversity_discr else None,
|
|
1303
|
+
has_diversity_discr_warmed_up = self.has_diversity_discr_warmed_up.item(),
|
|
1304
|
+
actor_optim = unwrap_optim(self.actor_optim).state_dict(),
|
|
1305
|
+
critic_optim = unwrap_optim(self.critic_optim).state_dict(),
|
|
1306
|
+
latent_optim = unwrap_optim(self.latent_optim).state_dict() if exists(self.latent_optim) else None,
|
|
1307
|
+
diversity_discr_optim = unwrap_optim(self.diversity_discr_optim).state_dict() if self.use_diversity_discr else None,
|
|
1230
1308
|
)
|
|
1231
1309
|
|
|
1232
1310
|
torch.save(pkg, str(path))
|
|
1233
1311
|
|
|
1234
1312
|
def load(self, path):
|
|
1235
1313
|
unwrap = self.unwrap_model
|
|
1314
|
+
unwrap_optim = lambda opt: opt.optimizer if hasattr(opt, 'optimizer') else opt
|
|
1236
1315
|
path = Path(path)
|
|
1237
1316
|
|
|
1238
1317
|
assert path.exists()
|
|
@@ -1240,20 +1319,28 @@ class Agent(Module):
|
|
|
1240
1319
|
pkg = torch.load(str(path), weights_only = True)
|
|
1241
1320
|
|
|
1242
1321
|
unwrap(self.actor).load_state_dict(pkg['actor'])
|
|
1243
|
-
|
|
1244
1322
|
unwrap(self.critic).load_state_dict(pkg['critic'])
|
|
1245
1323
|
|
|
1246
1324
|
if self.use_critic_ema:
|
|
1247
1325
|
self.critic_ema.load_state_dict(pkg['critic_ema'])
|
|
1248
1326
|
|
|
1249
|
-
if exists(pkg
|
|
1327
|
+
if 'latents' in pkg and exists(pkg['latents']):
|
|
1250
1328
|
self.latent_gene_pool.load_state_dict(pkg['latents'])
|
|
1251
1329
|
|
|
1252
|
-
|
|
1253
|
-
|
|
1330
|
+
if self.use_diversity_discr and 'diversity_discr' in pkg and exists(pkg['diversity_discr']):
|
|
1331
|
+
unwrap(self.diversity_discr).load_state_dict(pkg['diversity_discr'])
|
|
1332
|
+
|
|
1333
|
+
if 'has_diversity_discr_warmed_up' in pkg:
|
|
1334
|
+
self.has_diversity_discr_warmed_up.copy_(tensor(pkg['has_diversity_discr_warmed_up']))
|
|
1335
|
+
|
|
1336
|
+
unwrap_optim(self.actor_optim).load_state_dict(pkg['actor_optim'])
|
|
1337
|
+
unwrap_optim(self.critic_optim).load_state_dict(pkg['critic_optim'])
|
|
1338
|
+
|
|
1339
|
+
if 'latent_optim' in pkg and exists(pkg['latent_optim']):
|
|
1340
|
+
unwrap_optim(self.latent_optim).load_state_dict(pkg['latent_optim'])
|
|
1254
1341
|
|
|
1255
|
-
if exists(pkg
|
|
1256
|
-
|
|
1342
|
+
if self.use_diversity_discr and 'diversity_discr_optim' in pkg and exists(pkg['diversity_discr_optim']):
|
|
1343
|
+
unwrap_optim(self.diversity_discr_optim).load_state_dict(pkg['diversity_discr_optim'])
|
|
1257
1344
|
|
|
1258
1345
|
@move_input_tensors_to_device
|
|
1259
1346
|
def get_actor_actions(
|
|
@@ -1430,11 +1517,28 @@ class Agent(Module):
|
|
|
1430
1517
|
self.critic_optim.step()
|
|
1431
1518
|
self.critic_optim.zero_grad()
|
|
1432
1519
|
|
|
1520
|
+
# learn diversity discriminator
|
|
1521
|
+
|
|
1522
|
+
diversity_discr_loss = self.zero
|
|
1523
|
+
|
|
1524
|
+
if self.use_diversity_discr:
|
|
1525
|
+
diversity_discr_logits = self.diversity_discr(states, actions)
|
|
1526
|
+
diversity_discr_loss = F.cross_entropy(diversity_discr_logits, latent_gene_ids)
|
|
1527
|
+
|
|
1528
|
+
diversity_discr_loss.backward()
|
|
1529
|
+
|
|
1530
|
+
if exists(self.has_grad_clip):
|
|
1531
|
+
self.clip_grad_norm_(self.diversity_discr.parameters(), self.max_grad_norm)
|
|
1532
|
+
|
|
1533
|
+
self.diversity_discr_optim.step()
|
|
1534
|
+
self.diversity_discr_optim.zero_grad()
|
|
1535
|
+
|
|
1433
1536
|
# log actor critic loss
|
|
1434
1537
|
|
|
1435
1538
|
self.log(
|
|
1436
1539
|
actor_loss = actor_loss.item(),
|
|
1437
1540
|
critic_loss = critic_loss.item(),
|
|
1541
|
+
diversity_discr_loss = diversity_discr_loss.item(),
|
|
1438
1542
|
fitness_scores = fitness_scores
|
|
1439
1543
|
)
|
|
1440
1544
|
|
|
@@ -1475,10 +1579,27 @@ class Agent(Module):
|
|
|
1475
1579
|
for _, states, *_ in tqdm(dataloader, desc = 'state norm learning'):
|
|
1476
1580
|
self.state_norm(states)
|
|
1477
1581
|
|
|
1582
|
+
# update warmed up state for discriminator
|
|
1583
|
+
|
|
1584
|
+
if self.use_diversity_discr:
|
|
1585
|
+
self.has_diversity_discr_warmed_up.copy_(tensor(True))
|
|
1586
|
+
|
|
1478
1587
|
# apply evolution
|
|
1479
1588
|
|
|
1480
1589
|
if self.has_latent_genes:
|
|
1481
|
-
self.latent_gene_pool.genetic_algorithm_step(fitness_scores)
|
|
1590
|
+
should_update, _ = self.latent_gene_pool.genetic_algorithm_step(fitness_scores)
|
|
1591
|
+
|
|
1592
|
+
if self.use_diversity_discr and should_update:
|
|
1593
|
+
self.has_diversity_discr_warmed_up.copy_(tensor(False))
|
|
1594
|
+
|
|
1595
|
+
# reset discriminator
|
|
1596
|
+
|
|
1597
|
+
unwrap = self.unwrap_model
|
|
1598
|
+
unwrap(self.diversity_discr).reset_parameters()
|
|
1599
|
+
|
|
1600
|
+
# reset optimizer
|
|
1601
|
+
|
|
1602
|
+
self.diversity_discr_optim.state.clear()
|
|
1482
1603
|
|
|
1483
1604
|
# maybe shrink and perturb
|
|
1484
1605
|
|
|
@@ -1623,11 +1744,13 @@ class EPO(Module):
|
|
|
1623
1744
|
episodes_per_latent,
|
|
1624
1745
|
max_episode_length,
|
|
1625
1746
|
action_sample_temperature = 1.,
|
|
1626
|
-
fix_environ_across_latents = True
|
|
1747
|
+
fix_environ_across_latents = True,
|
|
1748
|
+
diversity_reward_weight = 1.,
|
|
1627
1749
|
):
|
|
1628
1750
|
super().__init__()
|
|
1629
1751
|
self.agent = agent
|
|
1630
1752
|
self.action_sample_temperature = action_sample_temperature
|
|
1753
|
+
self.diversity_reward_weight = diversity_reward_weight
|
|
1631
1754
|
|
|
1632
1755
|
self.num_latents = agent.latent_gene_pool.num_latents if agent.has_latent_genes else 1
|
|
1633
1756
|
self.episodes_per_latent = episodes_per_latent
|
|
@@ -1635,6 +1758,7 @@ class EPO(Module):
|
|
|
1635
1758
|
self.fix_environ_across_latents = fix_environ_across_latents
|
|
1636
1759
|
|
|
1637
1760
|
self.register_buffer('dummy', tensor(0, device = agent.device))
|
|
1761
|
+
self.register_buffer('zero', tensor(0., device = agent.device))
|
|
1638
1762
|
|
|
1639
1763
|
@property
|
|
1640
1764
|
def device(self):
|
|
@@ -1741,6 +1865,20 @@ class EPO(Module):
|
|
|
1741
1865
|
|
|
1742
1866
|
state, reward, truncated, terminated, _ = interface_torch_numpy(env.step, device = self.device)(action)
|
|
1743
1867
|
|
|
1868
|
+
# diversity reward
|
|
1869
|
+
|
|
1870
|
+
if self.agent.use_diversity_discr and self.agent.has_diversity_discr_warmed_up.item():
|
|
1871
|
+
with torch.no_grad():
|
|
1872
|
+
diversity_discr = self.agent.unwrap_model(self.agent.diversity_discr)
|
|
1873
|
+
diversity_discr.eval()
|
|
1874
|
+
|
|
1875
|
+
logits = diversity_discr(rearrange(state, '... -> 1 ...'), rearrange(action, '... -> 1 ...'))
|
|
1876
|
+
log_probs = logits.log_softmax(dim=-1)
|
|
1877
|
+
|
|
1878
|
+
diversity_reward = log_probs[0, latent_id] + log(tensor(self.agent.num_latents))
|
|
1879
|
+
|
|
1880
|
+
reward = reward + diversity_reward * self.diversity_reward_weight
|
|
1881
|
+
|
|
1744
1882
|
done = truncated or terminated
|
|
1745
1883
|
|
|
1746
1884
|
# update cumulative rewards per latent, to be used as default fitness score
|
|
@@ -7,6 +7,7 @@ import torch.nn.functional as F
|
|
|
7
7
|
from torch.func import vmap, functional_call
|
|
8
8
|
from torch.nn import Module, ParameterList
|
|
9
9
|
|
|
10
|
+
import einx
|
|
10
11
|
from einops import rearrange, reduce, repeat
|
|
11
12
|
|
|
12
13
|
def exists(v):
|
|
@@ -31,11 +32,12 @@ def shrink_and_perturb_(
|
|
|
31
32
|
|
|
32
33
|
def crossover_weights(
|
|
33
34
|
w1, w2,
|
|
35
|
+
alpha = 0.5,
|
|
34
36
|
shrink_perturb = False,
|
|
35
37
|
shrink_factor = 0.4,
|
|
36
38
|
perturb_factor = 0.1
|
|
37
39
|
):
|
|
38
|
-
assert
|
|
40
|
+
assert w1.shape == w2.shape
|
|
39
41
|
|
|
40
42
|
no_batch = w1.ndim == 2
|
|
41
43
|
|
|
@@ -58,12 +60,17 @@ def crossover_weights(
|
|
|
58
60
|
u1, s1, v1 = torch.svd(w1)
|
|
59
61
|
u2, s2, v2 = torch.svd(w2)
|
|
60
62
|
|
|
63
|
+
sign = einx.dot('b j d, b j d -> b d', v1, v2).sign()
|
|
64
|
+
|
|
65
|
+
u2 = einx.multiply('b i d, b d -> b i d', u2, sign)
|
|
66
|
+
v2 = einx.multiply('b j d, b d -> b j d', v2, sign)
|
|
67
|
+
|
|
61
68
|
batch_randperm = torch.randn((batch, rank), device = w1.device).argsort(dim = -1)
|
|
62
|
-
mask = batch_randperm < (rank
|
|
69
|
+
mask = batch_randperm < int(rank * alpha)
|
|
63
70
|
|
|
64
|
-
u =
|
|
65
|
-
s =
|
|
66
|
-
v =
|
|
71
|
+
u = einx.where('b d, b i d, b i d -> b i d', mask, u1, u2)
|
|
72
|
+
s = einx.where('b d, b d, b d -> b d', mask, s1, s2)
|
|
73
|
+
v = einx.where('b d, b j d, b j d -> b j d', mask, v1, v2)
|
|
67
74
|
|
|
68
75
|
out = u @ torch.diag_embed(s) @ v.mT
|
|
69
76
|
|
{evolutionary_policy_optimization-0.2.16 → evolutionary_policy_optimization-0.2.19}/pyproject.toml
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "evolutionary-policy-optimization"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.19"
|
|
4
4
|
description = "EPO - Pytorch"
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Phil Wang", email = "lucidrains@gmail.com" }
|
|
@@ -32,7 +32,8 @@ dependencies = [
|
|
|
32
32
|
'ema-pytorch>=0.7.7',
|
|
33
33
|
'hl-gauss-pytorch>=0.1.19',
|
|
34
34
|
'torch>=2.2',
|
|
35
|
-
'tqdm'
|
|
35
|
+
'tqdm',
|
|
36
|
+
"x-mlps-pytorch>=0.3.0",
|
|
36
37
|
]
|
|
37
38
|
|
|
38
39
|
[project.urls]
|
{evolutionary_policy_optimization-0.2.16 → evolutionary_policy_optimization-0.2.19}/.gitignore
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|