streaming-deep-rl 0.3.2__tar.gz → 0.3.4__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.4
2
2
  Name: streaming-deep-rl
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: Streaming Deep Reinforcement Learning
5
5
  Project-URL: Homepage, https://pypi.org/project/streaming-deep-rl/
6
6
  Project-URL: Repository, https://codeberg.org/lucidrains/streaming-deep-rl
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "streaming-deep-rl"
3
- version = "0.3.2"
3
+ version = "0.3.4"
4
4
  description = "Streaming Deep Reinforcement Learning"
5
5
  authors = [
6
6
  { name = "Phil Wang", email = "lucidrains@gmail.com" }
@@ -5,7 +5,7 @@ from typing import NamedTuple, Literal
5
5
 
6
6
  import torch
7
7
  import torch.nn.functional as F
8
- from torch import nn, tensor, is_tensor, cat, Tensor
8
+ from torch import nn, tensor, is_tensor, cat, stack, Tensor
9
9
  from torch.nn import Module, Linear, Sequential
10
10
  from torch.nn.utils import parameters_to_vector
11
11
 
@@ -186,6 +186,7 @@ class SelfPredictRepr(Module):
186
186
  dim_predict = None,
187
187
  target_embed_from_ema = True, # whether the target embed is from an EMA, or from the model itself (traditional vs sigreg from lejepa)
188
188
  sigreg_weight = 0.,
189
+ sigreg_num_subspaces = 1,
189
190
  dim_hidden_expand_factor = 4,
190
191
  use_sem = True,
191
192
  sem_dim_simplex = 8,
@@ -215,6 +216,18 @@ class SelfPredictRepr(Module):
215
216
  self.apply_sigreg = sigreg_weight > 0.
216
217
  self.sigreg_weight = sigreg_weight
217
218
 
219
+ # sub-jepa subspace gaussian regularization
220
+ # Kai Zhao et al https://arxiv.org/abs/2605.09241v1
221
+
222
+ self.num_subspaces = sigreg_num_subspaces
223
+
224
+ if self.num_subspaces > 1:
225
+ dim_subspace, remainder = divmod(dim_predict, self.num_subspaces)
226
+ assert remainder == 0, f'dimension {dim_predict} must be divisible by number of subspaces {self.num_subspaces}'
227
+
228
+ projs = stack([nn.init.orthogonal_(torch.empty(dim_subspace, dim_predict)) for _ in range(self.num_subspaces)])
229
+ self.register_buffer('subspace_projs', projs)
230
+
218
231
  self.use_sem = use_sem
219
232
  self.sem = SEM(dim_predict, dim_in = dim_embed, project_in = True, temperature = sem_temperature, dim_simplex = sem_dim_simplex) if use_sem else nn.Identity()
220
233
 
@@ -252,7 +265,14 @@ class SelfPredictRepr(Module):
252
265
  total_loss = recon_loss
253
266
 
254
267
  if self.apply_sigreg:
255
- total_loss = total_loss + self.sigreg_weight * sigreg(projected)
268
+ sigreg_input = projected
269
+
270
+ if self.num_subspaces > 1:
271
+ sigreg_input = einx.dot('... dim, k dim_subspace dim -> k ... dim_subspace', sigreg_input, self.subspace_projs)
272
+ else:
273
+ sigreg_input = rearrange(sigreg_input, '... d -> 1 ... d')
274
+
275
+ total_loss = total_loss + self.sigreg_weight * sigreg(sigreg_input)
256
276
 
257
277
  return SSLLosses(total = total_loss, recon = recon_loss)
258
278
 
@@ -357,6 +377,7 @@ def sigreg(
357
377
  mask = None
358
378
  ):
359
379
  # Randall Balestriero - https://arxiv.org/abs/2511.08544
380
+ # Sub-JEPA - https://arxiv.org/abs/2605.09241v1
360
381
 
361
382
  dim, device = x.shape[-1], x.device
362
383
 
@@ -375,13 +396,13 @@ def sigreg(
375
396
 
376
397
  # empirical CF
377
398
 
378
- x_t = einx.dot('... d, m d -> (...) m', x, rand_projs)
399
+ x_t = einx.dot('k ... d, m d -> k (...) m', x, rand_projs)
379
400
 
380
- x_t = einx.multiply('n m, t -> n m t', x_t, t)
401
+ x_t = einx.multiply('k n m, t -> k n m t', x_t, t)
381
402
  ecf = (1j * x_t).exp()
382
403
 
383
- mask_1d = rearrange(mask, '... -> (...)') if exists(mask) else None
384
- ecf = masked_mean(ecf, mask_1d, dim = 0)
404
+ mask_1d = rearrange(mask, 'k ... -> k (...)') if exists(mask) else None
405
+ ecf = masked_mean(ecf, mask_1d, dim = 1)
385
406
 
386
407
  # weighted L2 distance
387
408
 
@@ -1032,8 +1053,8 @@ class StreamingACLambda(Module):
1032
1053
 
1033
1054
  td_error_factor = td_error.abs().clamp(min = 1.)
1034
1055
 
1035
- actor_grad_norm = torch.stack([g.norm(p = 1) for g in actor_grad.values()]).mean()
1036
- critic_grad_norm = torch.stack([g.norm(p = 1) for g in value_grad.values()]).mean()
1056
+ actor_grad_norm = stack([g.norm(p = 1) for g in actor_grad.values()]).mean()
1057
+ critic_grad_norm = stack([g.norm(p = 1) for g in value_grad.values()]).mean()
1037
1058
 
1038
1059
  if self.adaptive:
1039
1060
  self.step.add_(1)
@@ -1076,9 +1097,9 @@ class StreamingACLambda(Module):
1076
1097
  enc_names = [n for n in spr_grads.keys() if n.startswith('0.')]
1077
1098
  enc_spr_updates = [-spr_grads[n] * self.spr_lr_param_update for n in enc_names]
1078
1099
  enc_rl_updates = [rl_updates[n] for n in enc_names]
1079
-
1100
+
1080
1101
  enc_spr_updates_proj = orthog_project_tensors(enc_spr_updates, enc_rl_updates)
1081
-
1102
+
1082
1103
  spr_updates_proj = {n: g for n, g in zip(enc_names, enc_spr_updates_proj)}
1083
1104
  else:
1084
1105
  spr_updates_proj = {}