BonanDing commited on
Commit
310850d
·
1 Parent(s): 09306ff

Clean up DeMemWM naming and memory path

Browse files
algorithms/dememwm/__init__.py CHANGED
@@ -1,37 +1,2 @@
1
- from collections.abc import Mapping
2
-
3
- from omegaconf import open_dict
4
-
5
- from .df_video import WorldMemMinecraft
6
  from .pose_prediction import PosePrediction
7
-
8
-
9
- _SEGMENT_KEYS = ("anchor", "dynamic", "revisit")
10
-
11
-
12
- def _cfg_get(cfg, key: str, default=None):
13
- if cfg is None:
14
- return default
15
- if isinstance(cfg, Mapping):
16
- return cfg.get(key, default)
17
- return getattr(cfg, key, default)
18
-
19
-
20
- def _derive_memory_condition_length(cfg) -> int:
21
- memory_cfg = _cfg_get(cfg, "memory_selection")
22
- if memory_cfg is None:
23
- value = _cfg_get(cfg, "memory_condition_length")
24
- if value is None:
25
- raise ValueError("DeMemWM requires memory_selection or memory_condition_length")
26
- return int(value)
27
- return sum(int(_cfg_get(memory_cfg, f"max_{key}_frames", 0)) for key in _SEGMENT_KEYS)
28
-
29
-
30
- class DeMemWMMinecraft(WorldMemMinecraft):
31
- """DeMemWM namespace wrapper for the copied WorldMem video algorithm."""
32
-
33
- def __init__(self, cfg):
34
- if _cfg_get(cfg, "memory_condition_length") is None:
35
- with open_dict(cfg):
36
- cfg.memory_condition_length = _derive_memory_condition_length(cfg)
37
- super().__init__(cfg)
 
1
+ from .df_video import DeMemWMMinecraft
 
 
 
 
2
  from .pose_prediction import PosePrediction
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
algorithms/dememwm/df_video.py CHANGED
@@ -12,7 +12,7 @@ from PIL import Image
12
  from packaging import version as pver
13
  from einops import rearrange
14
  from tqdm import tqdm
15
- from omegaconf import DictConfig
16
  from lightning.pytorch.utilities.types import STEP_OUTPUT
17
  from algorithms.common.metrics import (
18
  LearnedPerceptualImagePatchSimilarity,
@@ -29,6 +29,24 @@ _DEMEMWM_SEGMENT_KEYS = ("target", "anchor", "dynamic", "revisit")
29
  _DEMEMWM_STREAM_KEYS = ("anchor", "dynamic", "revisit")
30
 
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  def _segment_value_to_int(value, key):
33
  if torch.is_tensor(value):
34
  flat = value.reshape(-1)
@@ -432,18 +450,22 @@ def save_tensor_as_png(tensor, file_path):
432
  # Save image
433
  image.save(file_path)
434
 
435
- class WorldMemMinecraft(DiffusionForcingBase):
436
  """
437
- Video generation for MineCraft with memory.
438
  """
439
 
440
  def __init__(self, cfg: DictConfig):
441
  """
442
- Initialize the WorldMemMinecraft class with the given configuration.
443
 
444
  Args:
445
  cfg (DictConfig): Configuration object.
446
  """
 
 
 
 
447
  self.n_tokens = cfg.n_frames // cfg.frame_stack # number of max tokens for the model
448
  self.n_frames = cfg.n_frames
449
  if hasattr(cfg, "n_tokens"):
@@ -471,7 +493,9 @@ class WorldMemMinecraft(DiffusionForcingBase):
471
  def _build_model(self):
472
 
473
  self.diffusion_model = Diffusion(
474
- reference_length=self.memory_condition_length,
 
 
475
  x_shape=self.x_stacked_shape,
476
  action_cond_dim=self.action_cond_dim,
477
  pose_cond_dim=self.pose_cond_dim,
 
12
  from packaging import version as pver
13
  from einops import rearrange
14
  from tqdm import tqdm
15
+ from omegaconf import DictConfig, open_dict
16
  from lightning.pytorch.utilities.types import STEP_OUTPUT
17
  from algorithms.common.metrics import (
18
  LearnedPerceptualImagePatchSimilarity,
 
29
  _DEMEMWM_STREAM_KEYS = ("anchor", "dynamic", "revisit")
30
 
31
 
32
+ def _cfg_get(cfg, key: str, default=None):
33
+ if cfg is None:
34
+ return default
35
+ if isinstance(cfg, Mapping):
36
+ return cfg.get(key, default)
37
+ return getattr(cfg, key, default)
38
+
39
+
40
+ def _derive_memory_condition_length(cfg) -> int:
41
+ memory_cfg = _cfg_get(cfg, "memory_selection")
42
+ if memory_cfg is None:
43
+ value = _cfg_get(cfg, "memory_condition_length")
44
+ if value is None:
45
+ raise ValueError("DeMemWM requires memory_selection or memory_condition_length")
46
+ return int(value)
47
+ return sum(int(_cfg_get(memory_cfg, f"max_{key}_frames", 0)) for key in _DEMEMWM_STREAM_KEYS)
48
+
49
+
50
  def _segment_value_to_int(value, key):
51
  if torch.is_tensor(value):
52
  flat = value.reshape(-1)
 
450
  # Save image
451
  image.save(file_path)
452
 
453
+ class DeMemWMMinecraft(DiffusionForcingBase):
454
  """
455
+ DeMemWM video generation for MineCraft with frame memory.
456
  """
457
 
458
  def __init__(self, cfg: DictConfig):
459
  """
460
+ Initialize the DeMemWMMinecraft class with the given configuration.
461
 
462
  Args:
463
  cfg (DictConfig): Configuration object.
464
  """
465
+ if _cfg_get(cfg, "memory_condition_length") is None:
466
+ with open_dict(cfg):
467
+ cfg.memory_condition_length = _derive_memory_condition_length(cfg)
468
+
469
  self.n_tokens = cfg.n_frames // cfg.frame_stack # number of max tokens for the model
470
  self.n_frames = cfg.n_frames
471
  if hasattr(cfg, "n_tokens"):
 
493
  def _build_model(self):
494
 
495
  self.diffusion_model = Diffusion(
496
+ # DeMemWM injects memory through explicit frame_memory_segments;
497
+ # keep the legacy reference_length path disabled by default.
498
+ reference_length=0,
499
  x_shape=self.x_stacked_shape,
500
  action_cond_dim=self.action_cond_dim,
501
  pose_cond_dim=self.pose_cond_dim,
algorithms/dememwm/models/attention.py CHANGED
@@ -3,13 +3,11 @@ Based on https://github.com/buoyancy99/diffusion-forcing/blob/main/algorithms/di
3
  """
4
 
5
  from typing import Optional
6
- from collections import namedtuple
7
  import torch
8
  from torch import nn
9
  from torch.nn import functional as F
10
  from einops import rearrange
11
  from .rotary_embedding_torch import RotaryEmbedding, apply_rotary_emb
12
- import numpy as np
13
 
14
  class TemporalAxialAttention(nn.Module):
15
  def __init__(
@@ -224,179 +222,3 @@ class SpatialAxialAttention(nn.Module):
224
  # linear proj
225
  x = self.to_out(x)
226
  return x
227
-
228
- class MemTemporalAxialAttention(nn.Module):
229
- def __init__(
230
- self,
231
- dim: int,
232
- heads: int,
233
- dim_head: int,
234
- rotary_emb: RotaryEmbedding,
235
- is_causal: bool = True,
236
- ):
237
- super().__init__()
238
- self.inner_dim = dim_head * heads
239
- self.heads = heads
240
- self.head_dim = dim_head
241
- self.inner_dim = dim_head * heads
242
- self.to_qkv = nn.Linear(dim, self.inner_dim * 3, bias=False)
243
- self.to_out = nn.Linear(self.inner_dim, dim)
244
-
245
- self.rotary_emb = rotary_emb
246
- self.is_causal = is_causal
247
-
248
- self.reference_length = 3
249
-
250
- def forward(self, x: torch.Tensor):
251
- B, T, H, W, D = x.shape
252
-
253
- q, k, v = self.to_qkv(x).chunk(3, dim=-1)
254
-
255
-
256
- q = rearrange(q, "B T H W (h d) -> (B H W) h T d", h=self.heads)
257
- k = rearrange(k, "B T H W (h d) -> (B H W) h T d", h=self.heads)
258
- v = rearrange(v, "B T H W (h d) -> (B H W) h T d", h=self.heads)
259
-
260
-
261
-
262
- # q = self.rotary_emb.rotate_queries_or_keys(q, self.rotary_emb.freqs)
263
- # k = self.rotary_emb.rotate_queries_or_keys(k, self.rotary_emb.freqs)
264
-
265
- q, k, v = map(lambda t: t.contiguous(), (q, k, v))
266
-
267
- # if T == 21000:
268
- # # 手动计算缩放点积分数
269
- # _, _, _, d_k = q.shape
270
- # scores = torch.einsum("b h n d, b h m d -> b h n m", q, k) / (d_k ** 0.5) # Shape: (B, T_q, T_k)
271
-
272
- # # 计算注意力图 (Attention Map)
273
- # attention_map = F.softmax(scores, dim=-1) # Shape: (B, T_q, T_k)
274
- # b_, h_, n_, m_ = attention_map.shape
275
- # attention_map = attention_map.reshape(1, int(np.sqrt(b_/1)), int(np.sqrt(b_/1)), h_, n_, m_)
276
- # attention_map = attention_map.mean(3)
277
-
278
- # attn_bias = torch.zeros((T, T), dtype=q.dtype, device=q.device)
279
- # T_origin = T - self.reference_length
280
- # attn_bias[:T_origin, T_origin:] = 1
281
- # attn_bias[range(T), range(T)] = 1
282
-
283
- # attention_map = attention_map * attn_bias
284
-
285
- # # print 注意力图
286
- # import matplotlib.pyplot as plt
287
- # fig, axes = plt.subplots(21000, 21000, figsize=(9, 9)) # 调整figsize以适配图像大小
288
-
289
- # # 遍历3*3维度
290
- # for i in range(21000):
291
- # for j in range(21000):
292
- # # 取出第(i, j)个子图像
293
- # img = attention_map[0, :, :, i, j].cpu().numpy()
294
- # axes[i, j].imshow(img, cmap='viridis') # 可以自定义cmap
295
- # axes[i, j].axis('off') # 隐藏坐标轴
296
-
297
- # # 调整子图间距
298
- # plt.tight_layout()
299
- # plt.savefig('attention_map.png')
300
- # import pdb; pdb.set_trace()
301
- # plt.close()
302
-
303
- attn_bias = torch.zeros((T, T), dtype=q.dtype, device=q.device)
304
- attn_bias = attn_bias.masked_fill(attn_bias == 0, float('-inf'))
305
- T_origin = T - self.reference_length
306
- attn_bias[:T_origin, T_origin:] = 0
307
- attn_bias[range(T), range(T)] = 0
308
-
309
- # if T==121000:
310
- # import pdb;pdb.set_trace()
311
-
312
- try:
313
- x = F.scaled_dot_product_attention(query=q, key=k, value=v, attn_mask=attn_bias)
314
- except:
315
- import pdb;pdb.set_trace()
316
-
317
- x = rearrange(x, "(B H W) h T d -> B T H W (h d)", B=B, H=H, W=W)
318
- x = x.to(q.dtype)
319
-
320
- # linear proj
321
- x = self.to_out(x)
322
- return x
323
-
324
- class MemFullAttention(nn.Module):
325
- def __init__(
326
- self,
327
- dim: int,
328
- heads: int,
329
- dim_head: int,
330
- reference_length: int,
331
- rotary_emb: RotaryEmbedding,
332
- is_causal: bool = True
333
- ):
334
- super().__init__()
335
- self.inner_dim = dim_head * heads
336
- self.heads = heads
337
- self.head_dim = dim_head
338
- self.inner_dim = dim_head * heads
339
- self.to_qkv = nn.Linear(dim, self.inner_dim * 3, bias=False)
340
- self.to_out = nn.Linear(self.inner_dim, dim)
341
-
342
- self.rotary_emb = rotary_emb
343
- self.is_causal = is_causal
344
-
345
- self.reference_length = reference_length
346
-
347
- self.store = None
348
-
349
- def forward(self, x: torch.Tensor, relative_embedding=False,
350
- extra_condition=None,
351
- state_embed_only_on_qk=False,
352
- reference_length=None):
353
-
354
- B, T, H, W, D = x.shape
355
-
356
- if state_embed_only_on_qk:
357
- q, k, _ = self.to_qkv(x+extra_condition).chunk(3, dim=-1)
358
- _, _, v = self.to_qkv(x).chunk(3, dim=-1)
359
- else:
360
- q, k, v = self.to_qkv(x).chunk(3, dim=-1)
361
-
362
- if relative_embedding:
363
- length = reference_length+1
364
- n_frames = T // length
365
- x = x.reshape(B, n_frames, length, H, W, D)
366
-
367
- x_list = []
368
-
369
- for i in range(n_frames):
370
- if i == n_frames-1:
371
- q_i = rearrange(q[:, i*length:], "B T H W (h d) -> B h (T H W) d", h=self.heads)
372
- k_i = rearrange(k[:, i*length+1:(i+1)*length], "B T H W (h d) -> B h (T H W) d", h=self.heads)
373
- v_i = rearrange(v[:, i*length+1:(i+1)*length], "B T H W (h d) -> B h (T H W) d", h=self.heads)
374
- else:
375
- q_i = rearrange(q[:, i*length:i*length+1], "B T H W (h d) -> B h (T H W) d", h=self.heads)
376
- k_i = rearrange(k[:, i*length+1:(i+1)*length], "B T H W (h d) -> B h (T H W) d", h=self.heads)
377
- v_i = rearrange(v[:, i*length+1:(i+1)*length], "B T H W (h d) -> B h (T H W) d", h=self.heads)
378
-
379
- q_i, k_i, v_i = map(lambda t: t.contiguous(), (q_i, k_i, v_i))
380
- x_i = F.scaled_dot_product_attention(query=q_i, key=k_i, value=v_i)
381
- x_i = rearrange(x_i, "B h (T H W) d -> B T H W (h d)", B=B, H=H, W=W)
382
- x_i = x_i.to(q.dtype)
383
- x_list.append(x_i)
384
-
385
- x = torch.cat(x_list, dim=1)
386
-
387
-
388
- else:
389
- T_ = T - reference_length
390
- q = rearrange(q, "B T H W (h d) -> B h (T H W) d", h=self.heads)
391
- k = rearrange(k[:, T_:], "B T H W (h d) -> B h (T H W) d", h=self.heads)
392
- v = rearrange(v[:, T_:], "B T H W (h d) -> B h (T H W) d", h=self.heads)
393
-
394
- q, k, v = map(lambda t: t.contiguous(), (q, k, v))
395
- x = F.scaled_dot_product_attention(query=q, key=k, value=v)
396
- x = rearrange(x, "B h (T H W) d -> B T H W (h d)", B=B, H=H, W=W)
397
- x = x.to(q.dtype)
398
-
399
- # linear proj
400
- x = self.to_out(x)
401
-
402
- return x
 
3
  """
4
 
5
  from typing import Optional
 
6
  import torch
7
  from torch import nn
8
  from torch.nn import functional as F
9
  from einops import rearrange
10
  from .rotary_embedding_torch import RotaryEmbedding, apply_rotary_emb
 
11
 
12
  class TemporalAxialAttention(nn.Module):
13
  def __init__(
 
222
  # linear proj
223
  x = self.to_out(x)
224
  return x
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
algorithms/dememwm/models/diffusion.py CHANGED
@@ -360,7 +360,7 @@ class Diffusion(nn.Module):
360
  else:
361
  raise ValueError(f"unknown objective {self.objective}")
362
 
363
- # 训练的时候每个frame随便给噪声
364
  loss = F.mse_loss(pred, target.detach(), reduction="none")
365
  loss_weight = self.compute_loss_weights(target_noise_levels)
366
 
 
360
  else:
361
  raise ValueError(f"unknown objective {self.objective}")
362
 
363
+ # Give random noise to each frame during training
364
  loss = F.mse_loss(pred, target.detach(), reduction="none")
365
  loss_weight = self.compute_loss_weights(target_noise_levels)
366
 
algorithms/dememwm/models/dit.py CHANGED
@@ -11,7 +11,7 @@ from torch import nn
11
  from torch.nn import functional as F
12
  from .rotary_embedding_torch import RotaryEmbedding
13
  from einops import rearrange
14
- from .attention import SpatialAxialAttention, TemporalAxialAttention, MemTemporalAxialAttention, MemFullAttention
15
  from timm.models.vision_transformer import Mlp
16
  from timm.layers.helpers import to_2tuple
17
  import math
@@ -258,24 +258,6 @@ class SpatioTemporalDiTBlock(nn.Module):
258
  self.use_memory_attention = use_memory_attention
259
  if self.use_memory_attention:
260
  self.r_norm1 = nn.LayerNorm(hidden_size, elementwise_affine=False, eps=1e-6)
261
- self.ref_type = "full_ref"
262
- if self.ref_type == "temporal_ref":
263
- self.r_attn = MemTemporalAxialAttention(
264
- hidden_size,
265
- heads=num_heads,
266
- dim_head=hidden_size // num_heads,
267
- is_causal=is_causal,
268
- rotary_emb=None
269
- )
270
- elif self.ref_type == "full_ref":
271
- self.r_attn = MemFullAttention(
272
- hidden_size,
273
- heads=num_heads,
274
- dim_head=hidden_size // num_heads,
275
- is_causal=is_causal,
276
- rotary_emb=reference_rotary_emb,
277
- reference_length=reference_length
278
- )
279
  self.r_norm2 = nn.LayerNorm(hidden_size, elementwise_affine=False, eps=1e-6)
280
  self.r_mlp = Mlp(
281
  in_features=hidden_size,
@@ -284,11 +266,9 @@ class SpatioTemporalDiTBlock(nn.Module):
284
  drop=0,
285
  )
286
  self.r_adaLN_modulation = nn.Sequential(nn.SiLU(), nn.Linear(hidden_size, 6 * hidden_size, bias=True))
287
-
288
- self.use_plucker = use_plucker
289
- if use_plucker:
290
- self.pose_cond_mlp = nn.Linear(hidden_size, hidden_size)
291
- self.temporal_pose_cond_mlp = nn.Linear(hidden_size, hidden_size)
292
 
293
  self.reference_length = reference_length
294
  self.relative_embedding = relative_embedding
@@ -299,11 +279,6 @@ class SpatioTemporalDiTBlock(nn.Module):
299
  if self.ref_mode == 'parallel':
300
  self.parallel_map = nn.Linear(hidden_size, hidden_size)
301
 
302
- if self.use_memory_attention:
303
- self.r_attn_anchor = FrameMemoryReferenceAttention(hidden_size, num_heads)
304
- self.r_attn_dynamic = FrameMemoryReferenceAttention(hidden_size, num_heads)
305
- self.r_attn_revisit = FrameMemoryReferenceAttention(hidden_size, num_heads)
306
-
307
  def _split_frame_memory(self, x, frame_memory_segments):
308
  target = int(frame_memory_segments.get("target", 0))
309
  anchor = int(frame_memory_segments.get("anchor", 0))
@@ -389,8 +364,6 @@ class SpatioTemporalDiTBlock(nn.Module):
389
  x = x_t
390
 
391
  # memory block
392
- relative_embedding = self.relative_embedding # and mode == "training"
393
-
394
  if self.use_memory_attention and frame_memory_segments is not None:
395
  x = self._apply_frame_memory_reference_attention(
396
  x,
@@ -399,74 +372,12 @@ class SpatioTemporalDiTBlock(nn.Module):
399
  frame_memory_masks,
400
  frame_memory_geometry,
401
  )
402
- elif self.use_memory_attention:
403
- reference_length = self.reference_length if reference_length is None else reference_length
404
- r_shift_msa, r_scale_msa, r_gate_msa, r_shift_mlp, r_scale_mlp, r_gate_mlp = self.r_adaLN_modulation(c).chunk(6, dim=-1)
405
-
406
- if pose_cond is not None:
407
- if self.use_plucker:
408
- input_cond = self.pose_cond_mlp(pose_cond)
409
-
410
- if relative_embedding:
411
- n_frames = x.shape[1] - reference_length
412
- x1_relative_embedding = []
413
- r_shift_msa_relative_embedding = []
414
- r_scale_msa_relative_embedding = []
415
- for i in range(n_frames):
416
- x1_relative_embedding.append(torch.cat([x[:,i:i+1], x[:, -reference_length:]], dim=1).clone())
417
- r_shift_msa_relative_embedding.append(torch.cat([r_shift_msa[:,i:i+1], r_shift_msa[:, -reference_length:]], dim=1).clone())
418
- r_scale_msa_relative_embedding.append(torch.cat([r_scale_msa[:,i:i+1], r_scale_msa[:, -reference_length:]], dim=1).clone())
419
- x1_zero_frame = torch.cat(x1_relative_embedding, dim=1)
420
- r_shift_msa = torch.cat(r_shift_msa_relative_embedding, dim=1)
421
- r_scale_msa = torch.cat(r_scale_msa_relative_embedding, dim=1)
422
-
423
- # if current_frame == 18:
424
- # import pdb;pdb.set_trace()
425
-
426
- if self.state_embed_only_on_qk:
427
- attn_input = x1_zero_frame
428
- extra_condition = input_cond
429
- else:
430
- attn_input = input_cond + x1_zero_frame
431
- extra_condition = None
432
- else:
433
- attn_input = input_cond + x
434
- extra_condition = None
435
- # print("input_cond2:", input_cond.abs().mean())
436
- # print("c:", c.abs().mean())
437
- # input_cond = x1
438
-
439
- x = x + gate(self.r_attn(modulate(self.r_norm1(attn_input), r_shift_msa, r_scale_msa),
440
- relative_embedding=relative_embedding,
441
- extra_condition=extra_condition,
442
- state_embed_only_on_qk=self.state_embed_only_on_qk,
443
- reference_length=reference_length), r_gate_msa)
444
- else:
445
- # pose_cond *= 0
446
- x = x + gate(self.r_attn(modulate(self.r_norm1(x+pose_cond[:,:,None, None]), r_shift_msa, r_scale_msa),
447
- reference_length=reference_length), r_gate_msa)
448
- else:
449
- x = x + gate(self.r_attn(
450
- modulate(self.r_norm1(x), r_shift_msa, r_scale_msa),
451
- reference_length=reference_length,
452
- ), r_gate_msa)
453
-
454
- x = x + gate(self.r_mlp(modulate(self.r_norm2(x), r_shift_mlp, r_scale_mlp)), r_gate_mlp)
455
 
456
  if self.ref_mode == 'parallel':
457
  x = x_t + self.parallel_map(x)
458
 
459
  return x
460
 
461
- # print((x1-x2).abs().sum())
462
- # r_shift_msa, r_scale_msa, r_gate_msa, r_shift_mlp, r_scale_mlp, r_gate_mlp = self.r_adaLN_modulation(c).chunk(6, dim=-1)
463
- # x2 = x1 + gate(self.r_attn(modulate(self.r_norm1(x_), r_shift_msa, r_scale_msa)), r_gate_msa)
464
- # x2 = gate(self.r_mlp(modulate(self.r_norm2(x2), r_shift_mlp, r_scale_mlp)), r_gate_mlp)
465
- # x = x1 + x2
466
-
467
- # print(x.mean())
468
- # return x
469
-
470
 
471
  class DiT(nn.Module):
472
  """
@@ -589,10 +500,6 @@ class DiT(nn.Module):
589
  nn.init.constant_(block.t_adaLN_modulation[-1].weight, 0)
590
  nn.init.constant_(block.t_adaLN_modulation[-1].bias, 0)
591
 
592
- if self.use_plucker and self.use_memory_attention:
593
- nn.init.constant_(block.pose_cond_mlp.weight, 0)
594
- nn.init.constant_(block.pose_cond_mlp.bias, 0)
595
-
596
  # Zero-out output layers:
597
  nn.init.constant_(self.final_layer.adaLN_modulation[-1].weight, 0)
598
  nn.init.constant_(self.final_layer.adaLN_modulation[-1].bias, 0)
 
11
  from torch.nn import functional as F
12
  from .rotary_embedding_torch import RotaryEmbedding
13
  from einops import rearrange
14
+ from .attention import SpatialAxialAttention, TemporalAxialAttention
15
  from timm.models.vision_transformer import Mlp
16
  from timm.layers.helpers import to_2tuple
17
  import math
 
258
  self.use_memory_attention = use_memory_attention
259
  if self.use_memory_attention:
260
  self.r_norm1 = nn.LayerNorm(hidden_size, elementwise_affine=False, eps=1e-6)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
261
  self.r_norm2 = nn.LayerNorm(hidden_size, elementwise_affine=False, eps=1e-6)
262
  self.r_mlp = Mlp(
263
  in_features=hidden_size,
 
266
  drop=0,
267
  )
268
  self.r_adaLN_modulation = nn.Sequential(nn.SiLU(), nn.Linear(hidden_size, 6 * hidden_size, bias=True))
269
+ self.r_attn_anchor = FrameMemoryReferenceAttention(hidden_size, num_heads)
270
+ self.r_attn_dynamic = FrameMemoryReferenceAttention(hidden_size, num_heads)
271
+ self.r_attn_revisit = FrameMemoryReferenceAttention(hidden_size, num_heads)
 
 
272
 
273
  self.reference_length = reference_length
274
  self.relative_embedding = relative_embedding
 
279
  if self.ref_mode == 'parallel':
280
  self.parallel_map = nn.Linear(hidden_size, hidden_size)
281
 
 
 
 
 
 
282
  def _split_frame_memory(self, x, frame_memory_segments):
283
  target = int(frame_memory_segments.get("target", 0))
284
  anchor = int(frame_memory_segments.get("anchor", 0))
 
364
  x = x_t
365
 
366
  # memory block
 
 
367
  if self.use_memory_attention and frame_memory_segments is not None:
368
  x = self._apply_frame_memory_reference_attention(
369
  x,
 
372
  frame_memory_masks,
373
  frame_memory_geometry,
374
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
 
376
  if self.ref_mode == 'parallel':
377
  x = x_t + self.parallel_map(x)
378
 
379
  return x
380
 
 
 
 
 
 
 
 
 
 
381
 
382
  class DiT(nn.Module):
383
  """
 
500
  nn.init.constant_(block.t_adaLN_modulation[-1].weight, 0)
501
  nn.init.constant_(block.t_adaLN_modulation[-1].bias, 0)
502
 
 
 
 
 
503
  # Zero-out output layers:
504
  nn.init.constant_(self.final_layer.adaLN_modulation[-1].weight, 0)
505
  nn.init.constant_(self.final_layer.adaLN_modulation[-1].bias, 0)
tests/test_dememwm_latent_dataset.py CHANGED
@@ -226,7 +226,7 @@ class DeMemWMLatentDatasetTests(unittest.TestCase):
226
  self.assertEqual(preprocessed["image_hw"].tolist(), [[720, 1280], [720, 1280]])
227
 
228
  def test_training_step_uses_latent_dict_target_loss_and_memory_metadata(self):
229
- from algorithms.dememwm.df_video import WorldMemMinecraft, _preprocess_dememwm_latent_batch
230
 
231
  class FakeDiffusion:
232
  stabilization_level = 7
@@ -281,7 +281,7 @@ class DeMemWMLatentDatasetTests(unittest.TestCase):
281
  }
282
  harness = Harness()
283
 
284
- output = WorldMemMinecraft.training_step(harness, batch, 0)
285
  call = harness.diffusion_model
286
 
287
  self.assertEqual(harness.noise_input_shape, (2, 1, 1, 1, 1))
@@ -301,7 +301,7 @@ class DeMemWMLatentDatasetTests(unittest.TestCase):
301
  self.assertEqual(float(harness.logged[0][1]), 2.0)
302
 
303
  def test_validation_step_uses_latent_dict_target_sampling_and_metric(self):
304
- from algorithms.dememwm.df_video import WorldMemMinecraft, _preprocess_dememwm_latent_batch
305
 
306
  class FakeDiffusion:
307
  def __init__(self):
@@ -372,7 +372,7 @@ class DeMemWMLatentDatasetTests(unittest.TestCase):
372
  }
373
  harness = Harness()
374
 
375
- loss = WorldMemMinecraft.validation_step(harness, batch, 0, namespace="test")
376
  calls = harness.diffusion_model.calls
377
 
378
  self.assertEqual(harness.horizons, [2])
 
226
  self.assertEqual(preprocessed["image_hw"].tolist(), [[720, 1280], [720, 1280]])
227
 
228
  def test_training_step_uses_latent_dict_target_loss_and_memory_metadata(self):
229
+ from algorithms.dememwm.df_video import DeMemWMMinecraft, _preprocess_dememwm_latent_batch
230
 
231
  class FakeDiffusion:
232
  stabilization_level = 7
 
281
  }
282
  harness = Harness()
283
 
284
+ output = DeMemWMMinecraft.training_step(harness, batch, 0)
285
  call = harness.diffusion_model
286
 
287
  self.assertEqual(harness.noise_input_shape, (2, 1, 1, 1, 1))
 
301
  self.assertEqual(float(harness.logged[0][1]), 2.0)
302
 
303
  def test_validation_step_uses_latent_dict_target_sampling_and_metric(self):
304
+ from algorithms.dememwm.df_video import DeMemWMMinecraft, _preprocess_dememwm_latent_batch
305
 
306
  class FakeDiffusion:
307
  def __init__(self):
 
372
  }
373
  harness = Harness()
374
 
375
+ loss = DeMemWMMinecraft.validation_step(harness, batch, 0, namespace="test")
376
  calls = harness.diffusion_model.calls
377
 
378
  self.assertEqual(harness.horizons, [2])
tests/test_dememwm_temporal_attention.py CHANGED
@@ -194,6 +194,46 @@ class DeMemWMTemporalAttentionTests(unittest.TestCase):
194
  )
195
  self.assertEqual(tuple(packed_out.shape), (1, 2, 1, 2, 2))
196
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  def test_dit_builds_geometry_cache_once_and_threads_to_reference_attention(self):
198
  class ZeroAttention(nn.Module):
199
  def forward(self, x):
 
194
  )
195
  self.assertEqual(tuple(packed_out.shape), (1, 2, 1, 2, 2))
196
 
197
+ def test_dit_has_no_worldmem_reference_attention_fallback(self):
198
+ model = DiT(
199
+ input_h=2,
200
+ input_w=2,
201
+ patch_size=1,
202
+ in_channels=1,
203
+ hidden_size=8,
204
+ depth=1,
205
+ num_heads=1,
206
+ mlp_ratio=1.0,
207
+ action_cond_dim=3,
208
+ pose_cond_dim=0,
209
+ reference_length=1,
210
+ use_memory_attention=True,
211
+ )
212
+ block = model.blocks[0]
213
+
214
+ self.assertFalse(hasattr(block, "r_attn"))
215
+ self.assertFalse(hasattr(block, "pose_cond_mlp"))
216
+
217
+ calls = []
218
+
219
+ class SpyReferenceAttention(nn.Module):
220
+ def forward(self, target_hidden, memory_hidden, memory_mask=None, geometry_cache=None):
221
+ calls.append(memory_hidden)
222
+ return torch.zeros_like(target_hidden)
223
+
224
+ block.r_attn_anchor = SpyReferenceAttention()
225
+ block.r_attn_dynamic = SpyReferenceAttention()
226
+ block.r_attn_revisit = SpyReferenceAttention()
227
+
228
+ x = torch.randn((1, 3, 1, 2, 2))
229
+ t = torch.zeros((1, 3), dtype=torch.long)
230
+ action_cond = torch.zeros((1, 3, 3))
231
+ with torch.no_grad():
232
+ out = model(x, t, action_cond, reference_length=1)
233
+
234
+ self.assertEqual(tuple(out.shape), (1, 3, 1, 2, 2))
235
+ self.assertEqual(calls, [])
236
+
237
  def test_dit_builds_geometry_cache_once_and_threads_to_reference_attention(self):
238
  class ZeroAttention(nn.Module):
239
  def forward(self, x):