flaxdiff 0.2.10__tar.gz → 0.2.11__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.
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/PKG-INFO +2 -4
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/README.md +0 -2
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/models/hilbert.py +25 -20
- flaxdiff-0.2.11/flaxdiff/models/ssm_dit.py +560 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff.egg-info/PKG-INFO +2 -4
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff.egg-info/SOURCES.txt +1 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/pyproject.toml +2 -2
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/__init__.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/data/__init__.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/data/benchmark_decord.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/data/dataloaders.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/data/dataset_map.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/data/online_loader.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/data/sources/audio_utils.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/data/sources/av_example.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/data/sources/av_utils.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/data/sources/base.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/data/sources/images.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/data/sources/utils.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/data/sources/videos.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/data/sources/voxceleb2.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/inference/__init__.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/inference/pipeline.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/inference/utils.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/inputs/__init__.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/inputs/encoders.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/metrics/__init__.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/metrics/common.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/metrics/images.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/metrics/inception.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/metrics/psnr.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/metrics/ssim.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/metrics/utils.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/models/__init__.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/models/attention.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/models/autoencoder/__init__.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/models/autoencoder/autoencoder.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/models/autoencoder/diffusers.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/models/autoencoder/simple_autoenc.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/models/common.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/models/favor_fastattn.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/models/general.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/models/simple_dit.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/models/simple_mmdit.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/models/simple_unet.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/models/simple_vit.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/models/unet_3d.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/models/unet_3d_blocks.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/models/vit_common.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/predictors/__init__.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/samplers/__init__.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/samplers/common.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/samplers/ddim.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/samplers/ddpm.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/samplers/euler.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/samplers/heun_sampler.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/samplers/multistep_dpm.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/samplers/rk4_sampler.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/schedulers/__init__.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/schedulers/common.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/schedulers/continuous.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/schedulers/cosine.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/schedulers/discrete.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/schedulers/exp.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/schedulers/karras.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/schedulers/linear.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/schedulers/sqrt.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/trainer/__init__.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/trainer/autoencoder_trainer.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/trainer/diffusion_trainer.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/trainer/general_diffusion_trainer.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/trainer/simple_trainer.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff/utils.py +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff.egg-info/dependency_links.txt +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff.egg-info/requires.txt +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/flaxdiff.egg-info/top_level.txt +0 -0
- {flaxdiff-0.2.10 → flaxdiff-0.2.11}/setup.cfg +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flaxdiff
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.11
|
|
4
4
|
Summary: A versatile and easy to understand Diffusion library
|
|
5
5
|
Author-email: Ashish Kumar Singh <ashishkmr472@gmail.com>
|
|
6
|
-
License
|
|
6
|
+
License: MIT
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
Requires-Dist: flax>=0.8.4
|
|
9
9
|
Requires-Dist: jax>=0.4.28
|
|
@@ -22,8 +22,6 @@ Requires-Dist: python-dotenv
|
|
|
22
22
|
|
|
23
23
|
# 
|
|
24
24
|
|
|
25
|
-
**This project is being used for the UMD Course project MSML 605: MLOps**
|
|
26
|
-
|
|
27
25
|
**This project is partially supported by [Google TPU Research Cloud](https://sites.research.google/trc/about/). I would like to thank the Google Cloud TPU team for providing me with the resources to train the bigger text-conditional models in multi-host distributed settings.**
|
|
28
26
|
|
|
29
27
|
## A Versatile and simple Diffusion Library
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# 
|
|
2
2
|
|
|
3
|
-
**This project is being used for the UMD Course project MSML 605: MLOps**
|
|
4
|
-
|
|
5
3
|
**This project is partially supported by [Google TPU Research Cloud](https://sites.research.google/trc/about/). I would like to thank the Google Cloud TPU team for providing me with the resources to train the bigger text-conditional models in multi-host distributed settings.**
|
|
6
4
|
|
|
7
5
|
## A Versatile and simple Diffusion Library
|
|
@@ -241,7 +241,6 @@ def hilbert_unpatchify(x: jnp.ndarray, inv_idx: jnp.ndarray, patch_size: int, H:
|
|
|
241
241
|
target_shape = (B, total_patches_expected, patch_dim)
|
|
242
242
|
|
|
243
243
|
# Create indices for gathering from x (Hilbert order h) based on inv_idx (map k -> h)
|
|
244
|
-
# inv_idx contains the 'h' index for each 'k' index.
|
|
245
244
|
# Clamp invalid indices (-1) to 0; we'll mask these results later.
|
|
246
245
|
# Values must be < N (the actual number of patches in x).
|
|
247
246
|
h_indices_for_gather = jnp.maximum(inv_idx, 0) # Shape [total_patches_expected]
|
|
@@ -320,26 +319,37 @@ def visualize_hilbert_curve(H: int, W: int, patch_size: int, figsize=(12, 5)):
|
|
|
320
319
|
orig_grid = np.arange(H_P * W_P).reshape((H_P, W_P))
|
|
321
320
|
im0 = axes[0].imshow(orig_grid, cmap='viridis', aspect='auto')
|
|
322
321
|
axes[0].set_title(f"Original Grid ({H_P}x{W_P})\n(Row-Major Order)")
|
|
323
|
-
#
|
|
324
|
-
for r in range(H_P):
|
|
325
|
-
for c in range(W_P):
|
|
326
|
-
axes[0].text(c, r, f'{orig_grid[r, c]}', ha='center', va='center', color='white' if orig_grid[r,c] < (H_P*W_P)/2 else 'black', fontsize=8)
|
|
322
|
+
# Remove text labels for indices
|
|
327
323
|
axes[0].set_xticks(np.arange(W_P))
|
|
328
324
|
axes[0].set_yticks(np.arange(H_P))
|
|
329
325
|
axes[0].set_xticklabels(np.arange(W_P))
|
|
330
326
|
axes[0].set_yticklabels(np.arange(H_P))
|
|
331
327
|
plt.colorbar(im0, ax=axes[0], fraction=0.046, pad=0.04, label="Row-Major Index")
|
|
332
328
|
|
|
329
|
+
# Draw the row-major scanning line
|
|
330
|
+
if H_P * W_P > 1:
|
|
331
|
+
row_major_coords_y = []
|
|
332
|
+
row_major_coords_x = []
|
|
333
|
+
for r_idx in range(H_P * W_P):
|
|
334
|
+
r = r_idx // W_P
|
|
335
|
+
c = r_idx % W_P
|
|
336
|
+
row_major_coords_y.append(r + 0.5) # Cell center
|
|
337
|
+
row_major_coords_x.append(c + 0.5) # Cell center
|
|
338
|
+
axes[0].plot(row_major_coords_x, row_major_coords_y, color='red', linestyle='-', linewidth=1.5, alpha=0.8)
|
|
339
|
+
axes[0].plot(row_major_coords_x[0], row_major_coords_y[0], 'go', markersize=5, label='Start') # Smaller marker
|
|
340
|
+
axes[0].plot(row_major_coords_x[-1], row_major_coords_y[-1], 'mo', markersize=5, label='End') # Smaller marker
|
|
341
|
+
axes[0].legend(fontsize='x-small')
|
|
342
|
+
|
|
333
343
|
# --- Plot 2: Hilbert Curve Ordering ---
|
|
334
344
|
# Mask unmapped cells for visualization
|
|
335
345
|
masked_grid = np.ma.masked_where(grid == -1, grid)
|
|
336
346
|
im1 = axes[1].imshow(masked_grid, cmap=cmap, aspect='auto', vmin=0, vmax=max(0, len(idx)-1))
|
|
337
347
|
axes[1].set_title(f"Hilbert Curve Ordering ({len(idx)} points)")
|
|
338
348
|
# Add text labels for Hilbert indices
|
|
339
|
-
for r in range(H_P):
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
349
|
+
# for r in range(H_P):
|
|
350
|
+
# for c in range(W_P):
|
|
351
|
+
# if grid[r,c] != -1:
|
|
352
|
+
# axes[1].text(c, r, f'{int(grid[r, c])}', ha='center', va='center', color='black', fontsize=8)
|
|
343
353
|
axes[1].set_xticks(np.arange(W_P))
|
|
344
354
|
axes[1].set_yticks(np.arange(H_P))
|
|
345
355
|
axes[1].set_xticklabels(np.arange(W_P))
|
|
@@ -355,22 +365,17 @@ def visualize_hilbert_curve(H: int, W: int, patch_size: int, figsize=(12, 5)):
|
|
|
355
365
|
for i in range(len(idx)):
|
|
356
366
|
if i in row_col_map:
|
|
357
367
|
coords.append(row_col_map[i])
|
|
358
|
-
# Fallback (slower):
|
|
359
|
-
# row_indices, col_indices = np.where(grid == i)
|
|
360
|
-
# if len(row_indices) > 0:
|
|
361
|
-
# coords.append((row_indices[0], col_indices[0]))
|
|
362
368
|
|
|
363
369
|
if coords:
|
|
364
370
|
# Get coordinates for plotting (centers of cells)
|
|
365
|
-
y_coords = [r + 0.5 for r, c in coords]
|
|
366
|
-
x_coords = [c + 0.5 for r, c in coords]
|
|
367
|
-
axes[1].plot(x_coords, y_coords, color='
|
|
371
|
+
y_coords = [r + 0.5 for r, c in coords] # Cell center
|
|
372
|
+
x_coords = [c + 0.5 for r, c in coords] # Cell center
|
|
373
|
+
axes[1].plot(x_coords, y_coords, color='red', linestyle='-', linewidth=1.5, alpha=0.8) # Ensure Hilbert curve is red
|
|
368
374
|
# Mark start point
|
|
369
|
-
axes[1].plot(x_coords[0], y_coords[0], 'go', markersize=
|
|
375
|
+
axes[1].plot(x_coords[0], y_coords[0], 'go', markersize=5, label='Start') # Smaller marker
|
|
370
376
|
# Mark end point
|
|
371
|
-
axes[1].plot(x_coords[-1], y_coords[-1], 'mo', markersize=
|
|
372
|
-
axes[1].legend(fontsize='small')
|
|
373
|
-
|
|
377
|
+
axes[1].plot(x_coords[-1], y_coords[-1], 'mo', markersize=5, label='End') # Smaller marker
|
|
378
|
+
axes[1].legend(fontsize='x-small')
|
|
374
379
|
|
|
375
380
|
plt.tight_layout()
|
|
376
381
|
return fig
|
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SSM-based DiT Block and Hybrid SSM-Attention DiT for diffusion models.
|
|
3
|
+
|
|
4
|
+
Implements S5 (Simplified State Space) layers as a drop-in replacement for
|
|
5
|
+
attention in DiT blocks. The S5 layer uses diagonal state spaces with
|
|
6
|
+
JAX associative_scan for efficient parallel computation on TPUs.
|
|
7
|
+
|
|
8
|
+
References:
|
|
9
|
+
- Smith et al., "Simplified State Space Layers for Sequence Modeling", ICLR 2023
|
|
10
|
+
- Peebles & Xie, "Scalable Diffusion Models with Transformers", ICCV 2023
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import jax
|
|
14
|
+
import jax.numpy as jnp
|
|
15
|
+
from flax import linen as nn
|
|
16
|
+
from typing import Callable, Any, Optional, Tuple, Sequence, Union
|
|
17
|
+
import einops
|
|
18
|
+
from functools import partial
|
|
19
|
+
|
|
20
|
+
from .vit_common import PatchEmbedding, unpatchify, RotaryEmbedding, RoPEAttention, AdaLNParams
|
|
21
|
+
from .common import kernel_init, FourierEmbedding, TimeProjection
|
|
22
|
+
from .attention import NormalAttention
|
|
23
|
+
from flax.typing import Dtype, PrecisionLike
|
|
24
|
+
|
|
25
|
+
from .hilbert import hilbert_indices, inverse_permutation, hilbert_patchify, hilbert_unpatchify
|
|
26
|
+
from .simple_dit import DiTBlock
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# =============================================================================
|
|
30
|
+
# S5 SSM Layer - Diagonal State Space with Parallel Scan
|
|
31
|
+
# =============================================================================
|
|
32
|
+
|
|
33
|
+
def hippo_initializer(state_dim):
|
|
34
|
+
"""Initialize A matrix using HiPPO-LegS (Legendre State Space) framework.
|
|
35
|
+
|
|
36
|
+
For diagonal S5, we use the diagonal approximation of HiPPO.
|
|
37
|
+
Returns complex diagonal elements that capture long-range dependencies.
|
|
38
|
+
"""
|
|
39
|
+
def init(key, shape, dtype=jnp.float32):
|
|
40
|
+
# Diagonal HiPPO initialization: lambda_n = -(2n+1)/2 + i*pi*n
|
|
41
|
+
n = jnp.arange(state_dim)
|
|
42
|
+
real = -(n + 0.5)
|
|
43
|
+
imag = jnp.pi * n
|
|
44
|
+
# Normalize to unit circle for stability
|
|
45
|
+
lambda_init = real + 1j * imag
|
|
46
|
+
# Discretize with dt=1 for initialization, actual dt is learned
|
|
47
|
+
return lambda_init.astype(jnp.complex64)
|
|
48
|
+
return init
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class S5Layer(nn.Module):
|
|
52
|
+
"""S5 (Simplified State Space) layer with diagonal state matrix.
|
|
53
|
+
|
|
54
|
+
Processes sequences using state space recurrence:
|
|
55
|
+
x_k = A * x_{k-1} + B * u_k
|
|
56
|
+
y_k = Re(C * x_k) + D * u_k
|
|
57
|
+
|
|
58
|
+
Where A is diagonal (complex), enabling efficient parallel scan via
|
|
59
|
+
jax.lax.associative_scan. This is TPU-friendly as it maps to
|
|
60
|
+
prefix-sum operations on the systolic array.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
features: Output dimension (must match input for residual)
|
|
64
|
+
state_dim: Dimension of the hidden state (per feature)
|
|
65
|
+
dt_min: Minimum discretization step (log scale)
|
|
66
|
+
dt_max: Maximum discretization step (log scale)
|
|
67
|
+
dtype: Computation dtype
|
|
68
|
+
precision: JAX precision level
|
|
69
|
+
"""
|
|
70
|
+
features: int
|
|
71
|
+
state_dim: int = 64
|
|
72
|
+
dt_min: float = 0.001
|
|
73
|
+
dt_max: float = 0.1
|
|
74
|
+
dtype: Optional[Dtype] = None
|
|
75
|
+
precision: PrecisionLike = None
|
|
76
|
+
|
|
77
|
+
@nn.compact
|
|
78
|
+
def __call__(self, u):
|
|
79
|
+
"""
|
|
80
|
+
Args:
|
|
81
|
+
u: Input sequence [B, S, F]
|
|
82
|
+
Returns:
|
|
83
|
+
y: Output sequence [B, S, F]
|
|
84
|
+
"""
|
|
85
|
+
B, S, F = u.shape
|
|
86
|
+
|
|
87
|
+
# --- Learnable SSM Parameters ---
|
|
88
|
+
# A: Diagonal state matrix (complex) - initialized with HiPPO
|
|
89
|
+
# We parameterize as log of negative real part for stability
|
|
90
|
+
log_A_real = self.param(
|
|
91
|
+
'log_A_real',
|
|
92
|
+
nn.initializers.normal(stddev=0.5),
|
|
93
|
+
(self.state_dim,)
|
|
94
|
+
)
|
|
95
|
+
A_imag = self.param(
|
|
96
|
+
'A_imag',
|
|
97
|
+
nn.initializers.normal(stddev=0.5),
|
|
98
|
+
(self.state_dim,)
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# B: Input-to-state projection [state_dim, F]
|
|
102
|
+
B_re = self.param(
|
|
103
|
+
'B_re',
|
|
104
|
+
nn.initializers.lecun_normal(),
|
|
105
|
+
(self.state_dim, F)
|
|
106
|
+
)
|
|
107
|
+
B_im = self.param(
|
|
108
|
+
'B_im',
|
|
109
|
+
nn.initializers.lecun_normal(),
|
|
110
|
+
(self.state_dim, F)
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# C: State-to-output projection [F, state_dim]
|
|
114
|
+
C_re = self.param(
|
|
115
|
+
'C_re',
|
|
116
|
+
nn.initializers.lecun_normal(),
|
|
117
|
+
(F, self.state_dim)
|
|
118
|
+
)
|
|
119
|
+
C_im = self.param(
|
|
120
|
+
'C_im',
|
|
121
|
+
nn.initializers.lecun_normal(),
|
|
122
|
+
(F, self.state_dim)
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# D: Skip connection (direct input-to-output)
|
|
126
|
+
D = self.param('D', nn.initializers.ones, (F,))
|
|
127
|
+
|
|
128
|
+
# dt: Discretization timestep (learned, per-feature)
|
|
129
|
+
log_dt = self.param(
|
|
130
|
+
'log_dt',
|
|
131
|
+
lambda key, shape: jax.random.uniform(
|
|
132
|
+
key, shape,
|
|
133
|
+
minval=jnp.log(self.dt_min),
|
|
134
|
+
maxval=jnp.log(self.dt_max)
|
|
135
|
+
),
|
|
136
|
+
(F,)
|
|
137
|
+
)
|
|
138
|
+
dt = jnp.exp(log_dt) # [F]
|
|
139
|
+
|
|
140
|
+
# --- Construct complex A and discretize ---
|
|
141
|
+
# A_diag: complex diagonal [state_dim]
|
|
142
|
+
A_real = -jnp.exp(log_A_real) # Ensure negative real part for stability
|
|
143
|
+
A_diag = A_real + 1j * A_imag # [state_dim]
|
|
144
|
+
|
|
145
|
+
# ZOH discretization: A_bar = exp(A * dt), B_bar = (A_bar - I) * A^{-1} * B
|
|
146
|
+
# For diagonal A, this simplifies element-wise
|
|
147
|
+
# dt broadcasts: [F] -> we use mean dt for state transition
|
|
148
|
+
dt_mean = jnp.mean(dt)
|
|
149
|
+
A_bar = jnp.exp(A_diag * dt_mean) # [state_dim], complex
|
|
150
|
+
|
|
151
|
+
# B as complex: [state_dim, F]
|
|
152
|
+
B_complex = B_re + 1j * B_im
|
|
153
|
+
# Discretized B: element-wise
|
|
154
|
+
B_bar = ((A_bar[:, None] - 1.0) / (A_diag[:, None] + 1e-8)) * B_complex # [state_dim, F]
|
|
155
|
+
|
|
156
|
+
# C as complex: [F, state_dim]
|
|
157
|
+
C_complex = C_re + 1j * C_im
|
|
158
|
+
|
|
159
|
+
# --- Parallel Scan (associative scan for TPU efficiency) ---
|
|
160
|
+
# For diagonal SSM: x_k = A_bar * x_{k-1} + B_bar @ u_k
|
|
161
|
+
# This can be computed via associative scan with the binary operator:
|
|
162
|
+
# (a1, b1) * (a2, b2) = (a1 * a2, a2 * b1 + b2)
|
|
163
|
+
|
|
164
|
+
# Compute per-step inputs: B_bar @ u_k for each timestep
|
|
165
|
+
# u: [B, S, F], B_bar: [state_dim, F]
|
|
166
|
+
# Bu: [B, S, state_dim] (complex)
|
|
167
|
+
u_float = u.astype(jnp.float32)
|
|
168
|
+
Bu = jnp.einsum('bsf,nf->bsn', u_float, B_bar) # [B, S, state_dim]
|
|
169
|
+
|
|
170
|
+
# A_bar is the same for all timesteps: [state_dim]
|
|
171
|
+
# Expand for scan: [B, S, state_dim]
|
|
172
|
+
A_bar_expanded = jnp.broadcast_to(A_bar[None, None, :], (B, S, self.state_dim))
|
|
173
|
+
|
|
174
|
+
# Associative scan elements: (a, b) where a=A_bar, b=Bu
|
|
175
|
+
def binary_operator(e1, e2):
|
|
176
|
+
a1, b1 = e1
|
|
177
|
+
a2, b2 = e2
|
|
178
|
+
return a1 * a2, a2 * b1 + b2
|
|
179
|
+
|
|
180
|
+
# Run parallel scan along sequence dimension (axis=1)
|
|
181
|
+
_, x_states = jax.lax.associative_scan(
|
|
182
|
+
binary_operator,
|
|
183
|
+
(A_bar_expanded, Bu),
|
|
184
|
+
axis=1
|
|
185
|
+
)
|
|
186
|
+
# x_states: [B, S, state_dim] (complex) - hidden states at each step
|
|
187
|
+
|
|
188
|
+
# --- Output computation ---
|
|
189
|
+
# y_k = Re(C @ x_k) + D * u_k
|
|
190
|
+
# C: [F, state_dim], x_states: [B, S, state_dim]
|
|
191
|
+
y_complex = jnp.einsum('fn,bsn->bsf', C_complex, x_states) # [B, S, F]
|
|
192
|
+
y = y_complex.real # Take real part: [B, S, F]
|
|
193
|
+
|
|
194
|
+
# Add skip connection
|
|
195
|
+
y = y + D[None, None, :] * u_float # [B, S, F]
|
|
196
|
+
|
|
197
|
+
# Cast back to input dtype
|
|
198
|
+
if self.dtype is not None:
|
|
199
|
+
y = y.astype(self.dtype)
|
|
200
|
+
else:
|
|
201
|
+
y = y.astype(u.dtype)
|
|
202
|
+
|
|
203
|
+
return y
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
# =============================================================================
|
|
207
|
+
# Bidirectional S5 - processes sequence in both directions
|
|
208
|
+
# =============================================================================
|
|
209
|
+
|
|
210
|
+
class BidirectionalS5Layer(nn.Module):
|
|
211
|
+
"""Bidirectional S5 layer - runs forward and backward scans.
|
|
212
|
+
|
|
213
|
+
For diffusion models, spatial patches have no inherent directionality,
|
|
214
|
+
so bidirectional processing captures dependencies in both directions
|
|
215
|
+
along the serialization curve (Hilbert, raster, etc.).
|
|
216
|
+
|
|
217
|
+
Output is the sum of forward and backward scans, projected to features.
|
|
218
|
+
"""
|
|
219
|
+
features: int
|
|
220
|
+
state_dim: int = 64
|
|
221
|
+
dt_min: float = 0.001
|
|
222
|
+
dt_max: float = 0.1
|
|
223
|
+
dtype: Optional[Dtype] = None
|
|
224
|
+
precision: PrecisionLike = None
|
|
225
|
+
|
|
226
|
+
@nn.compact
|
|
227
|
+
def __call__(self, u):
|
|
228
|
+
"""
|
|
229
|
+
Args:
|
|
230
|
+
u: [B, S, F]
|
|
231
|
+
Returns:
|
|
232
|
+
y: [B, S, F]
|
|
233
|
+
"""
|
|
234
|
+
# Forward scan
|
|
235
|
+
y_fwd = S5Layer(
|
|
236
|
+
features=self.features,
|
|
237
|
+
state_dim=self.state_dim,
|
|
238
|
+
dt_min=self.dt_min,
|
|
239
|
+
dt_max=self.dt_max,
|
|
240
|
+
dtype=self.dtype,
|
|
241
|
+
precision=self.precision,
|
|
242
|
+
name="s5_forward"
|
|
243
|
+
)(u)
|
|
244
|
+
|
|
245
|
+
# Backward scan (reverse input, scan, reverse output)
|
|
246
|
+
u_rev = jnp.flip(u, axis=1)
|
|
247
|
+
y_bwd_rev = S5Layer(
|
|
248
|
+
features=self.features,
|
|
249
|
+
state_dim=self.state_dim,
|
|
250
|
+
dt_min=self.dt_min,
|
|
251
|
+
dt_max=self.dt_max,
|
|
252
|
+
dtype=self.dtype,
|
|
253
|
+
precision=self.precision,
|
|
254
|
+
name="s5_backward"
|
|
255
|
+
)(u_rev)
|
|
256
|
+
y_bwd = jnp.flip(y_bwd_rev, axis=1)
|
|
257
|
+
|
|
258
|
+
# Combine forward and backward
|
|
259
|
+
y = y_fwd + y_bwd
|
|
260
|
+
|
|
261
|
+
# Output projection to mix directions
|
|
262
|
+
y = nn.Dense(
|
|
263
|
+
features=self.features,
|
|
264
|
+
dtype=self.dtype,
|
|
265
|
+
precision=self.precision,
|
|
266
|
+
name="out_proj"
|
|
267
|
+
)(y)
|
|
268
|
+
|
|
269
|
+
return y
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
# =============================================================================
|
|
273
|
+
# SSMDiTBlock - Drop-in replacement for DiTBlock
|
|
274
|
+
# =============================================================================
|
|
275
|
+
|
|
276
|
+
class SSMDiTBlock(nn.Module):
|
|
277
|
+
"""SSM-based DiT Block that replaces attention with bidirectional S5.
|
|
278
|
+
|
|
279
|
+
Maintains the EXACT same interface as DiTBlock:
|
|
280
|
+
__call__(self, x, conditioning, freqs_cis) -> x
|
|
281
|
+
|
|
282
|
+
The AdaLN modulation, gating, residual connections, and MLP path
|
|
283
|
+
are IDENTICAL to DiTBlock. Only the attention is replaced with S5.
|
|
284
|
+
|
|
285
|
+
Note: freqs_cis (RoPE frequencies) is accepted for interface compatibility
|
|
286
|
+
but not used by the SSM - positional information is implicitly captured
|
|
287
|
+
by the sequential scan along the serialization order (Hilbert/raster/etc).
|
|
288
|
+
"""
|
|
289
|
+
features: int
|
|
290
|
+
num_heads: int # Not used by SSM, kept for interface compat
|
|
291
|
+
rope_emb: RotaryEmbedding # Not used by SSM, kept for interface compat
|
|
292
|
+
state_dim: int = 64
|
|
293
|
+
mlp_ratio: int = 4
|
|
294
|
+
dropout_rate: float = 0.0
|
|
295
|
+
dtype: Optional[Dtype] = None
|
|
296
|
+
precision: PrecisionLike = None
|
|
297
|
+
use_flash_attention: bool = False # Ignored, interface compat
|
|
298
|
+
force_fp32_for_softmax: bool = True # Ignored, interface compat
|
|
299
|
+
norm_epsilon: float = 1e-5
|
|
300
|
+
use_gating: bool = True
|
|
301
|
+
bidirectional: bool = True
|
|
302
|
+
|
|
303
|
+
def setup(self):
|
|
304
|
+
hidden_features = int(self.features * self.mlp_ratio)
|
|
305
|
+
|
|
306
|
+
# AdaLN modulation - IDENTICAL to DiTBlock
|
|
307
|
+
self.ada_params_module = AdaLNParams(
|
|
308
|
+
self.features, dtype=self.dtype, precision=self.precision)
|
|
309
|
+
|
|
310
|
+
# Layer Norms - IDENTICAL to DiTBlock
|
|
311
|
+
self.norm1 = nn.LayerNorm(
|
|
312
|
+
epsilon=self.norm_epsilon, use_scale=False, use_bias=False,
|
|
313
|
+
dtype=self.dtype, name="norm1")
|
|
314
|
+
self.norm2 = nn.LayerNorm(
|
|
315
|
+
epsilon=self.norm_epsilon, use_scale=False, use_bias=False,
|
|
316
|
+
dtype=self.dtype, name="norm2")
|
|
317
|
+
|
|
318
|
+
# S5 SSM layer (replaces attention)
|
|
319
|
+
ssm_cls = BidirectionalS5Layer if self.bidirectional else S5Layer
|
|
320
|
+
self.ssm = ssm_cls(
|
|
321
|
+
features=self.features,
|
|
322
|
+
state_dim=self.state_dim,
|
|
323
|
+
dtype=self.dtype,
|
|
324
|
+
precision=self.precision,
|
|
325
|
+
name="ssm"
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
# MLP - IDENTICAL to DiTBlock
|
|
329
|
+
self.mlp = nn.Sequential([
|
|
330
|
+
nn.Dense(features=hidden_features, dtype=self.dtype, precision=self.precision),
|
|
331
|
+
nn.gelu,
|
|
332
|
+
nn.Dense(features=self.features, dtype=self.dtype, precision=self.precision)
|
|
333
|
+
])
|
|
334
|
+
|
|
335
|
+
@nn.compact
|
|
336
|
+
def __call__(self, x, conditioning, freqs_cis):
|
|
337
|
+
"""Exact same signature as DiTBlock.__call__"""
|
|
338
|
+
# Get scale/shift/gate parameters - IDENTICAL to DiTBlock
|
|
339
|
+
scale_mlp, shift_mlp, gate_mlp, scale_attn, shift_attn, gate_attn = jnp.split(
|
|
340
|
+
self.ada_params_module(conditioning), 6, axis=-1
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
# --- SSM Path (replaces Attention Path) ---
|
|
344
|
+
residual = x
|
|
345
|
+
norm_x = self.norm1(x)
|
|
346
|
+
x_modulated = norm_x * (1 + scale_attn) + shift_attn
|
|
347
|
+
ssm_output = self.ssm(x_modulated)
|
|
348
|
+
|
|
349
|
+
if self.use_gating:
|
|
350
|
+
x = residual + gate_attn * ssm_output
|
|
351
|
+
else:
|
|
352
|
+
x = residual + ssm_output
|
|
353
|
+
|
|
354
|
+
# --- MLP Path --- IDENTICAL to DiTBlock
|
|
355
|
+
residual = x
|
|
356
|
+
norm_x_mlp = self.norm2(x)
|
|
357
|
+
x_mlp_modulated = norm_x_mlp * (1 + scale_mlp) + shift_mlp
|
|
358
|
+
mlp_output = self.mlp(x_mlp_modulated)
|
|
359
|
+
|
|
360
|
+
if self.use_gating:
|
|
361
|
+
x = residual + gate_mlp * mlp_output
|
|
362
|
+
else:
|
|
363
|
+
x = residual + mlp_output
|
|
364
|
+
|
|
365
|
+
return x
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
# =============================================================================
|
|
369
|
+
# HybridSSMAttentionDiT - The proposed novel architecture
|
|
370
|
+
# =============================================================================
|
|
371
|
+
|
|
372
|
+
class HybridSSMAttentionDiT(nn.Module):
|
|
373
|
+
"""Hybrid SSM-Attention Diffusion Transformer.
|
|
374
|
+
|
|
375
|
+
Interleaves SSM blocks (for O(n) local processing along Hilbert curve)
|
|
376
|
+
with attention blocks (for O(n^2) global composition) in a configurable
|
|
377
|
+
ratio. Both block types share the same AdaLN conditioning interface.
|
|
378
|
+
|
|
379
|
+
Args:
|
|
380
|
+
block_pattern: List of 'ssm' or 'attn' strings defining the block sequence.
|
|
381
|
+
Example: ['ssm','ssm','ssm','attn'] for 3:1 ratio repeated.
|
|
382
|
+
If None, uses ssm_attention_ratio to auto-generate pattern.
|
|
383
|
+
ssm_attention_ratio: Shorthand ratio like '3:1' (3 SSM per 1 attention).
|
|
384
|
+
Only used if block_pattern is None.
|
|
385
|
+
"""
|
|
386
|
+
output_channels: int = 3
|
|
387
|
+
patch_size: int = 16
|
|
388
|
+
emb_features: int = 768
|
|
389
|
+
num_layers: int = 12
|
|
390
|
+
num_heads: int = 12
|
|
391
|
+
mlp_ratio: int = 4
|
|
392
|
+
ssm_state_dim: int = 64
|
|
393
|
+
dropout_rate: float = 0.0
|
|
394
|
+
dtype: Optional[Dtype] = None
|
|
395
|
+
precision: PrecisionLike = None
|
|
396
|
+
use_flash_attention: bool = False
|
|
397
|
+
force_fp32_for_softmax: bool = True
|
|
398
|
+
norm_epsilon: float = 1e-5
|
|
399
|
+
learn_sigma: bool = False
|
|
400
|
+
use_hilbert: bool = False
|
|
401
|
+
norm_groups: int = 0
|
|
402
|
+
activation: Callable = jax.nn.swish
|
|
403
|
+
block_pattern: Optional[Sequence[str]] = None # e.g., ['ssm','ssm','ssm','attn']
|
|
404
|
+
ssm_attention_ratio: str = "3:1" # e.g., "3:1", "1:1", "all-ssm", "all-attn"
|
|
405
|
+
bidirectional_ssm: bool = True
|
|
406
|
+
|
|
407
|
+
def _build_block_pattern(self):
|
|
408
|
+
"""Generate block pattern from ratio string."""
|
|
409
|
+
if self.block_pattern is not None:
|
|
410
|
+
pattern = list(self.block_pattern)
|
|
411
|
+
elif self.ssm_attention_ratio == "all-ssm":
|
|
412
|
+
pattern = ['ssm'] * self.num_layers
|
|
413
|
+
elif self.ssm_attention_ratio == "all-attn":
|
|
414
|
+
pattern = ['attn'] * self.num_layers
|
|
415
|
+
else:
|
|
416
|
+
parts = self.ssm_attention_ratio.split(':')
|
|
417
|
+
n_ssm, n_attn = int(parts[0]), int(parts[1])
|
|
418
|
+
unit = ['ssm'] * n_ssm + ['attn'] * n_attn
|
|
419
|
+
pattern = (unit * (self.num_layers // len(unit) + 1))[:self.num_layers]
|
|
420
|
+
return pattern
|
|
421
|
+
|
|
422
|
+
def setup(self):
|
|
423
|
+
self.patch_embed = PatchEmbedding(
|
|
424
|
+
patch_size=self.patch_size,
|
|
425
|
+
embedding_dim=self.emb_features,
|
|
426
|
+
dtype=self.dtype,
|
|
427
|
+
precision=self.precision
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
if self.use_hilbert:
|
|
431
|
+
self.hilbert_proj = nn.Dense(
|
|
432
|
+
features=self.emb_features,
|
|
433
|
+
dtype=self.dtype,
|
|
434
|
+
precision=self.precision,
|
|
435
|
+
name="hilbert_projection"
|
|
436
|
+
)
|
|
437
|
+
|
|
438
|
+
# Time embedding
|
|
439
|
+
self.time_embed = nn.Sequential([
|
|
440
|
+
FourierEmbedding(features=self.emb_features),
|
|
441
|
+
TimeProjection(features=self.emb_features * self.mlp_ratio),
|
|
442
|
+
nn.Dense(features=self.emb_features, dtype=self.dtype, precision=self.precision)
|
|
443
|
+
])
|
|
444
|
+
|
|
445
|
+
# Text context projection
|
|
446
|
+
self.text_proj = nn.Dense(
|
|
447
|
+
features=self.emb_features, dtype=self.dtype,
|
|
448
|
+
precision=self.precision, name="text_context_proj")
|
|
449
|
+
|
|
450
|
+
# RoPE (used by attention blocks, passed through SSM blocks)
|
|
451
|
+
self.rope = RotaryEmbedding(
|
|
452
|
+
dim=self.emb_features // self.num_heads,
|
|
453
|
+
max_seq_len=4096, dtype=self.dtype)
|
|
454
|
+
|
|
455
|
+
# Build hybrid block sequence
|
|
456
|
+
pattern = self._build_block_pattern()
|
|
457
|
+
blocks = []
|
|
458
|
+
for i, block_type in enumerate(pattern):
|
|
459
|
+
if block_type == 'ssm':
|
|
460
|
+
blocks.append(SSMDiTBlock(
|
|
461
|
+
features=self.emb_features,
|
|
462
|
+
num_heads=self.num_heads,
|
|
463
|
+
rope_emb=self.rope,
|
|
464
|
+
state_dim=self.ssm_state_dim,
|
|
465
|
+
mlp_ratio=self.mlp_ratio,
|
|
466
|
+
dropout_rate=self.dropout_rate,
|
|
467
|
+
dtype=self.dtype,
|
|
468
|
+
precision=self.precision,
|
|
469
|
+
norm_epsilon=self.norm_epsilon,
|
|
470
|
+
bidirectional=self.bidirectional_ssm,
|
|
471
|
+
name=f"ssm_block_{i}"
|
|
472
|
+
))
|
|
473
|
+
else: # 'attn'
|
|
474
|
+
blocks.append(DiTBlock(
|
|
475
|
+
features=self.emb_features,
|
|
476
|
+
num_heads=self.num_heads,
|
|
477
|
+
rope_emb=self.rope,
|
|
478
|
+
mlp_ratio=self.mlp_ratio,
|
|
479
|
+
dropout_rate=self.dropout_rate,
|
|
480
|
+
dtype=self.dtype,
|
|
481
|
+
precision=self.precision,
|
|
482
|
+
use_flash_attention=self.use_flash_attention,
|
|
483
|
+
force_fp32_for_softmax=self.force_fp32_for_softmax,
|
|
484
|
+
norm_epsilon=self.norm_epsilon,
|
|
485
|
+
name=f"dit_block_{i}"
|
|
486
|
+
))
|
|
487
|
+
self.blocks = blocks
|
|
488
|
+
|
|
489
|
+
# Final layer
|
|
490
|
+
self.final_norm = nn.LayerNorm(
|
|
491
|
+
epsilon=self.norm_epsilon, dtype=self.dtype, name="final_norm")
|
|
492
|
+
|
|
493
|
+
output_dim = self.patch_size * self.patch_size * self.output_channels
|
|
494
|
+
if self.learn_sigma:
|
|
495
|
+
output_dim *= 2
|
|
496
|
+
|
|
497
|
+
self.final_proj = nn.Dense(
|
|
498
|
+
features=output_dim,
|
|
499
|
+
dtype=self.dtype,
|
|
500
|
+
precision=self.precision,
|
|
501
|
+
kernel_init=nn.initializers.zeros,
|
|
502
|
+
name="final_proj"
|
|
503
|
+
)
|
|
504
|
+
|
|
505
|
+
@nn.compact
|
|
506
|
+
def __call__(self, x, temb, textcontext=None):
|
|
507
|
+
"""Exact same signature as SimpleDiT.__call__"""
|
|
508
|
+
B, H, W, C = x.shape
|
|
509
|
+
assert H % self.patch_size == 0 and W % self.patch_size == 0
|
|
510
|
+
|
|
511
|
+
H_P = H // self.patch_size
|
|
512
|
+
W_P = W // self.patch_size
|
|
513
|
+
|
|
514
|
+
# 1. Patch Embedding (identical to SimpleDiT)
|
|
515
|
+
if self.use_hilbert:
|
|
516
|
+
patches_raw, hilbert_inv_idx = hilbert_patchify(x, self.patch_size)
|
|
517
|
+
patches = self.hilbert_proj(patches_raw)
|
|
518
|
+
else:
|
|
519
|
+
patches = self.patch_embed(x)
|
|
520
|
+
hilbert_inv_idx = None
|
|
521
|
+
|
|
522
|
+
num_patches = patches.shape[1]
|
|
523
|
+
x_seq = patches
|
|
524
|
+
|
|
525
|
+
# 2. Conditioning (identical to SimpleDiT)
|
|
526
|
+
t_emb = self.time_embed(temb)
|
|
527
|
+
cond_emb = t_emb
|
|
528
|
+
if textcontext is not None:
|
|
529
|
+
text_emb = self.text_proj(textcontext)
|
|
530
|
+
text_emb_pooled = jnp.mean(text_emb, axis=1)
|
|
531
|
+
cond_emb = cond_emb + text_emb_pooled
|
|
532
|
+
|
|
533
|
+
# 3. RoPE frequencies
|
|
534
|
+
freqs_cos, freqs_sin = self.rope(seq_len=num_patches)
|
|
535
|
+
|
|
536
|
+
# 4. Hybrid blocks (SSM and attention interleaved)
|
|
537
|
+
for block in self.blocks:
|
|
538
|
+
x_seq = block(x_seq, conditioning=cond_emb, freqs_cis=(freqs_cos, freqs_sin))
|
|
539
|
+
|
|
540
|
+
# 5. Final output (identical to SimpleDiT)
|
|
541
|
+
x_out = self.final_norm(x_seq)
|
|
542
|
+
x_out = self.final_proj(x_out)
|
|
543
|
+
|
|
544
|
+
# 6. Unpatchify
|
|
545
|
+
if self.use_hilbert:
|
|
546
|
+
if self.learn_sigma:
|
|
547
|
+
x_mean, x_logvar = jnp.split(x_out, 2, axis=-1)
|
|
548
|
+
x_image = hilbert_unpatchify(x_mean, hilbert_inv_idx, self.patch_size, H, W, self.output_channels)
|
|
549
|
+
return x_image
|
|
550
|
+
else:
|
|
551
|
+
x_image = hilbert_unpatchify(x_out, hilbert_inv_idx, self.patch_size, H, W, self.output_channels)
|
|
552
|
+
return x_image
|
|
553
|
+
else:
|
|
554
|
+
if self.learn_sigma:
|
|
555
|
+
x_mean, x_logvar = jnp.split(x_out, 2, axis=-1)
|
|
556
|
+
x = unpatchify(x_mean, channels=self.output_channels)
|
|
557
|
+
return x
|
|
558
|
+
else:
|
|
559
|
+
x = unpatchify(x_out, channels=self.output_channels)
|
|
560
|
+
return x
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flaxdiff
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.11
|
|
4
4
|
Summary: A versatile and easy to understand Diffusion library
|
|
5
5
|
Author-email: Ashish Kumar Singh <ashishkmr472@gmail.com>
|
|
6
|
-
License
|
|
6
|
+
License: MIT
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
Requires-Dist: flax>=0.8.4
|
|
9
9
|
Requires-Dist: jax>=0.4.28
|
|
@@ -22,8 +22,6 @@ Requires-Dist: python-dotenv
|
|
|
22
22
|
|
|
23
23
|
# 
|
|
24
24
|
|
|
25
|
-
**This project is being used for the UMD Course project MSML 605: MLOps**
|
|
26
|
-
|
|
27
25
|
**This project is partially supported by [Google TPU Research Cloud](https://sites.research.google/trc/about/). I would like to thank the Google Cloud TPU team for providing me with the resources to train the bigger text-conditional models in multi-host distributed settings.**
|
|
28
26
|
|
|
29
27
|
## A Versatile and simple Diffusion Library
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "flaxdiff"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.11"
|
|
8
8
|
description = "A versatile and easy to understand Diffusion library"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [
|
|
@@ -26,7 +26,7 @@ dependencies = [
|
|
|
26
26
|
"rich",
|
|
27
27
|
"python-dotenv",
|
|
28
28
|
]
|
|
29
|
-
license = "MIT"
|
|
29
|
+
license = {text = "MIT"}
|
|
30
30
|
|
|
31
31
|
[tool.setuptools.packages.find]
|
|
32
32
|
include = ["flaxdiff*"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|