nebulette commited on
Commit
39425c6
·
verified ·
1 Parent(s): 1d211bf

Update spectrum.py

Browse files
Files changed (1) hide show
  1. spectrum.py +24 -31
spectrum.py CHANGED
@@ -78,7 +78,7 @@ class SpectrumConfig:
78
  def window_cap(self) -> float:
79
  return max(1.0, self.window_size, float(self.history_points))
80
 
81
- def _cheb_basis(u, degree: int) -> torch.Tensor:
82
  u = torch.as_tensor(u, dtype=torch.float64).reshape(-1)
83
  cols = [torch.ones_like(u)]
84
  if degree >= 1:
@@ -87,7 +87,7 @@ def _cheb_basis(u, degree: int) -> torch.Tensor:
87
  cols.append(2.0 * u * cols[-1] - cols[-2])
88
  return torch.stack(cols[: degree + 1], dim=-1) # [n, P]
89
 
90
- class _Forecaster:
91
  """Chebyshev ridge forecaster (prediction = weighted sum of anchors)"""
92
  def __init__(self, cfg: SpectrumConfig):
93
  self.cfg = cfg
@@ -116,7 +116,7 @@ class _Forecaster:
116
  self._chol = None
117
 
118
  def _design(self) -> torch.Tensor:
119
- return _cheb_basis(self.us, self.cfg.chebyshev_degree) # [K, P]
120
 
121
  def _factor(self) -> torch.Tensor:
122
  if self._chol is not None:
@@ -160,7 +160,7 @@ class _Forecaster:
160
  return w
161
 
162
  def weights(self, u: float) -> torch.Tensor:
163
- phi = _cheb_basis([u], self.cfg.chebyshev_degree) # [1, P]
164
  solved = torch.cholesky_solve(self._design().T, self._factor()) # [P, K]
165
  spectral = (phi @ solved).reshape(-1)
166
  bw = self.cfg.blend_weight
@@ -194,7 +194,7 @@ class _Forecaster:
194
  den = actual.float().norm().clamp_min(1e-6)
195
  return float((num / den).item())
196
 
197
- class _Branch:
198
  """Per-branch scheduler state"""
199
  def __init__(self, cfg: SpectrumConfig):
200
  self.cfg = cfg
@@ -202,13 +202,13 @@ class _Branch:
202
  self.consecutive = 0
203
  self.actual = 0
204
  self.forecast = 0
205
- self.forecasters: dict[int, _Forecaster] = {}
206
  self.errors: list[float] = []
207
 
208
- def forecaster(self, sample: int) -> _Forecaster:
209
  f = self.forecasters.get(sample)
210
  if f is None:
211
- f = self.forecasters[sample] = _Forecaster(self.cfg)
212
  return f
213
 
214
  def decide(self, step: int, total: int) -> bool:
@@ -234,20 +234,20 @@ class _Branch:
234
  self.consecutive += 1
235
 
236
 
237
- class _State:
238
  def __init__(self, cfg: SpectrumConfig, scheduler: Any):
239
  self.cfg = cfg
240
  self.scheduler = scheduler
241
  self.original_forward = None
242
  self.step_index = -1
243
- self.branches: dict[Any, _Branch] = {}
244
  self._sig_counts: dict[Any, int] = {}
245
  self._log: list[str] = []
246
 
247
- def branch(self, key: Any) -> _Branch:
248
  b = self.branches.get(key)
249
  if b is None:
250
- b = self.branches[key] = _Branch(self.cfg)
251
  return b
252
 
253
  def reset_run(self) -> None:
@@ -266,20 +266,13 @@ class _State:
266
  f"{f}/{a + f} ({speed:.2f}x) mean_forecast_rel_err={mean_err:.4f}"
267
  )
268
 
269
- def _validate_skip_layers(layers, depth: int, name: str = "skip_layers") -> tuple:
270
  layers = () if layers is None else tuple(layers)
271
  if any(type(i) is not int or not 0 <= i < depth for i in layers):
272
  raise ValueError(f"{name} must contain integer block indices in [0, {depth}).")
273
  return layers
274
 
275
-
276
- def _coord(step: int, total: int) -> float:
277
- if total <= 1:
278
- return 0.0
279
- return max(-1.0, min(1.0, 2.0 * step / (total - 1) - 1.0))
280
-
281
-
282
- def _resolve_step(state: _State, timestep: torch.Tensor) -> tuple[int, int]:
283
  sched = state.scheduler
284
  timesteps = getattr(sched, "timesteps", None) if sched is not None else None
285
  if timesteps is None or len(timesteps) == 0:
@@ -289,7 +282,7 @@ def _resolve_step(state: _State, timestep: torch.Tensor) -> tuple[int, int]:
289
  idx = int((ts.float() - t).abs().argmin().item())
290
  return idx, len(ts)
291
 
292
- def _spectrum_forward(
293
  self,
294
  hidden_states: torch.Tensor,
295
  timestep,
@@ -302,7 +295,7 @@ def _spectrum_forward(
302
  License: Apache-2.0
303
  https://huggingface.co/nebulette/moss-spectrum-diffusers
304
  """
305
- state: Optional[_State] = getattr(self, "_spectrum_state", None)
306
  if state is None or state.scheduler is None:
307
  return state.original_forward(
308
  hidden_states, timestep, encoder_hidden_states,
@@ -311,7 +304,7 @@ def _spectrum_forward(
311
  )
312
 
313
  cfg = state.cfg
314
- skip = _validate_skip_layers(skip_layers, len(self.layers))
315
 
316
  if hidden_states.ndim != 4 or hidden_states.shape[1] != self.config.latent_channels:
317
  raise ValueError("hidden_states must be [B, latent_channels, H, W].")
@@ -326,7 +319,7 @@ def _spectrum_forward(
326
  raise ValueError("encoder_attention_mask must be a binary [B, S] mask.")
327
 
328
  # --- step bookkeeping ------------------------------------------------- #
329
- step, total = _resolve_step(state, timestep)
330
  if step < 0: # no schedule available -> stay exact
331
  return state.original_forward(
332
  hidden_states, timestep, encoder_hidden_states,
@@ -345,7 +338,7 @@ def _spectrum_forward(
345
  branch = state.branch((sig, occurrence))
346
 
347
  actual = branch.decide(step, total)
348
- u = _coord(step, total)
349
 
350
  # shared timestep conditioning (identical to the original)
351
  times = torch.as_tensor(timestep, device=hidden_states.device, dtype=torch.float32).reshape(-1).expand(batch)
@@ -374,7 +367,7 @@ def _spectrum_forward(
374
  # skip embeddings, text blocks and all layers
375
  try:
376
  feat = forecaster.predict(u)
377
- except Exception:
378
  # numerical trouble -> fall back to a real step
379
  actual = True
380
  branch.note(True, step)
@@ -428,11 +421,11 @@ def _spectrum_forward(
428
  return (sample,)
429
  return Transformer2DModelOutput(sample=sample)
430
 
431
-
432
  def apply_spectrum(pipe, config: Optional[SpectrumConfig] = None):
433
  """
434
  Patch ``pipe`` in place so the MOSS DiT runs under Spectrum scheduling.
435
-
436
  License: Apache-2.0
437
  https://huggingface.co/nebulette/moss-spectrum-diffusers
438
  """
@@ -446,11 +439,11 @@ def apply_spectrum(pipe, config: Optional[SpectrumConfig] = None):
446
  if getattr(transformer, "_spectrum_state", None) is not None:
447
  remove_spectrum(pipe)
448
 
449
- state = _State(cfg, getattr(pipe, "scheduler", None))
450
  state.original_forward = transformer.forward
451
 
452
  transformer._spectrum_state = state
453
- transformer.forward = types.MethodType(_spectrum_forward, transformer)
454
  return pipe
455
 
456
 
 
78
  def window_cap(self) -> float:
79
  return max(1.0, self.window_size, float(self.history_points))
80
 
81
+ def cheb_basis(u, degree: int) -> torch.Tensor:
82
  u = torch.as_tensor(u, dtype=torch.float64).reshape(-1)
83
  cols = [torch.ones_like(u)]
84
  if degree >= 1:
 
87
  cols.append(2.0 * u * cols[-1] - cols[-2])
88
  return torch.stack(cols[: degree + 1], dim=-1) # [n, P]
89
 
90
+ class Forecaster:
91
  """Chebyshev ridge forecaster (prediction = weighted sum of anchors)"""
92
  def __init__(self, cfg: SpectrumConfig):
93
  self.cfg = cfg
 
116
  self._chol = None
117
 
118
  def _design(self) -> torch.Tensor:
119
+ return cheb_basis(self.us, self.cfg.chebyshev_degree) # [K, P]
120
 
121
  def _factor(self) -> torch.Tensor:
122
  if self._chol is not None:
 
160
  return w
161
 
162
  def weights(self, u: float) -> torch.Tensor:
163
+ phi = cheb_basis([u], self.cfg.chebyshev_degree) # [1, P]
164
  solved = torch.cholesky_solve(self._design().T, self._factor()) # [P, K]
165
  spectral = (phi @ solved).reshape(-1)
166
  bw = self.cfg.blend_weight
 
194
  den = actual.float().norm().clamp_min(1e-6)
195
  return float((num / den).item())
196
 
197
+ class Branch:
198
  """Per-branch scheduler state"""
199
  def __init__(self, cfg: SpectrumConfig):
200
  self.cfg = cfg
 
202
  self.consecutive = 0
203
  self.actual = 0
204
  self.forecast = 0
205
+ self.forecasters: dict[int, Forecaster] = {}
206
  self.errors: list[float] = []
207
 
208
+ def forecaster(self, sample: int) -> Forecaster:
209
  f = self.forecasters.get(sample)
210
  if f is None:
211
+ f = self.forecasters[sample] = Forecaster(self.cfg)
212
  return f
213
 
214
  def decide(self, step: int, total: int) -> bool:
 
234
  self.consecutive += 1
235
 
236
 
237
+ class State:
238
  def __init__(self, cfg: SpectrumConfig, scheduler: Any):
239
  self.cfg = cfg
240
  self.scheduler = scheduler
241
  self.original_forward = None
242
  self.step_index = -1
243
+ self.branches: dict[Any, Branch] = {}
244
  self._sig_counts: dict[Any, int] = {}
245
  self._log: list[str] = []
246
 
247
+ def branch(self, key: Any) -> Branch:
248
  b = self.branches.get(key)
249
  if b is None:
250
+ b = self.branches[key] = Branch(self.cfg)
251
  return b
252
 
253
  def reset_run(self) -> None:
 
266
  f"{f}/{a + f} ({speed:.2f}x) mean_forecast_rel_err={mean_err:.4f}"
267
  )
268
 
269
+ def validate_skip_layers(layers, depth: int, name: str = "skip_layers") -> tuple:
270
  layers = () if layers is None else tuple(layers)
271
  if any(type(i) is not int or not 0 <= i < depth for i in layers):
272
  raise ValueError(f"{name} must contain integer block indices in [0, {depth}).")
273
  return layers
274
 
275
+ def resolve_step(state: State, timestep: torch.Tensor) -> tuple[int, int]:
 
 
 
 
 
 
 
276
  sched = state.scheduler
277
  timesteps = getattr(sched, "timesteps", None) if sched is not None else None
278
  if timesteps is None or len(timesteps) == 0:
 
282
  idx = int((ts.float() - t).abs().argmin().item())
283
  return idx, len(ts)
284
 
285
+ def spectrum_forward(
286
  self,
287
  hidden_states: torch.Tensor,
288
  timestep,
 
295
  License: Apache-2.0
296
  https://huggingface.co/nebulette/moss-spectrum-diffusers
297
  """
298
+ state: Optional[State] = getattr(self, "_spectrum_state", None)
299
  if state is None or state.scheduler is None:
300
  return state.original_forward(
301
  hidden_states, timestep, encoder_hidden_states,
 
304
  )
305
 
306
  cfg = state.cfg
307
+ skip = validate_skip_layers(skip_layers, len(self.layers))
308
 
309
  if hidden_states.ndim != 4 or hidden_states.shape[1] != self.config.latent_channels:
310
  raise ValueError("hidden_states must be [B, latent_channels, H, W].")
 
319
  raise ValueError("encoder_attention_mask must be a binary [B, S] mask.")
320
 
321
  # --- step bookkeeping ------------------------------------------------- #
322
+ step, total = resolve_step(state, timestep)
323
  if step < 0: # no schedule available -> stay exact
324
  return state.original_forward(
325
  hidden_states, timestep, encoder_hidden_states,
 
338
  branch = state.branch((sig, occurrence))
339
 
340
  actual = branch.decide(step, total)
341
+ u = 0.0 if total <= 1 else max(-1.0, min(1.0, 2.0 * step / (total - 1) - 1.0))
342
 
343
  # shared timestep conditioning (identical to the original)
344
  times = torch.as_tensor(timestep, device=hidden_states.device, dtype=torch.float32).reshape(-1).expand(batch)
 
367
  # skip embeddings, text blocks and all layers
368
  try:
369
  feat = forecaster.predict(u)
370
+ except Exception:
371
  # numerical trouble -> fall back to a real step
372
  actual = True
373
  branch.note(True, step)
 
421
  return (sample,)
422
  return Transformer2DModelOutput(sample=sample)
423
 
424
+
425
  def apply_spectrum(pipe, config: Optional[SpectrumConfig] = None):
426
  """
427
  Patch ``pipe`` in place so the MOSS DiT runs under Spectrum scheduling.
428
+
429
  License: Apache-2.0
430
  https://huggingface.co/nebulette/moss-spectrum-diffusers
431
  """
 
439
  if getattr(transformer, "_spectrum_state", None) is not None:
440
  remove_spectrum(pipe)
441
 
442
+ state = State(cfg, getattr(pipe, "scheduler", None))
443
  state.original_forward = transformer.forward
444
 
445
  transformer._spectrum_state = state
446
+ transformer.forward = types.MethodType(spectrum_forward, transformer)
447
  return pipe
448
 
449