Instructions to use ostris/primal_vae with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Diffusers
How to use ostris/primal_vae with Diffusers:
pip install -U diffusers transformers accelerate
import torch from diffusers import DiffusionPipeline # switch to "mps" for apple devices pipe = DiffusionPipeline.from_pretrained("ostris/primal_vae", dtype=torch.bfloat16, device_map="cuda") prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k" image = pipe(prompt).images[0] - Notebooks
- Google Colab
- Kaggle
Add gradient checkpointing to the vae
Browse files- README.md +3 -0
- __pycache__/modeling_primal_vae.cpython-312.pyc +0 -0
- modeling_primal_vae.py +13 -2
README.md
CHANGED
|
@@ -66,6 +66,9 @@ shapes, so `weights_name="my_finetune.safetensors"` loads any Primal VAE checkpo
|
|
| 66 |
`pixel_shuffle` by `compression / 2`, so `compression=8` is a 4x4 patch. `vae.token_channels(8)` and
|
| 67 |
`vae.image_multiple` give you the numbers above.
|
| 68 |
|
|
|
|
|
|
|
|
|
|
| 69 |
## Architecture
|
| 70 |
|
| 71 |
Both models are the same network, they only differ in output channels.
|
|
|
|
| 66 |
`pixel_shuffle` by `compression / 2`, so `compression=8` is a 4x4 patch. `vae.token_channels(8)` and
|
| 67 |
`vae.image_multiple` give you the numbers above.
|
| 68 |
|
| 69 |
+
To backprop through `decode` (a pixel-space loss on a diffusion model's prediction), `vae.enable_gradient_checkpointing()`
|
| 70 |
+
checkpoints every residual block of both U-Nets; inference under `torch.no_grad()` is unaffected.
|
| 71 |
+
|
| 72 |
## Architecture
|
| 73 |
|
| 74 |
Both models are the same network, they only differ in output channels.
|
__pycache__/modeling_primal_vae.cpython-312.pyc
ADDED
|
Binary file (18.9 kB). View file
|
|
|
modeling_primal_vae.py
CHANGED
|
@@ -15,6 +15,7 @@ from typing import List, Optional
|
|
| 15 |
import torch
|
| 16 |
import torch.nn as nn
|
| 17 |
import torch.nn.functional as F
|
|
|
|
| 18 |
from diffusers.configuration_utils import ConfigMixin, register_to_config
|
| 19 |
from diffusers.models.modeling_utils import ModelMixin
|
| 20 |
from huggingface_hub import hf_hub_download
|
|
@@ -66,6 +67,14 @@ class UStack(nn.Module):
|
|
| 66 |
self.up_blocks = nn.ModuleList([nn.ModuleList([ResBlock(widths[i], DILATION_CYCLE[j % len(DILATION_CYCLE)]) for j in range(up_depths[i])]) for i in range(L - 1)])
|
| 67 |
self.norm_out = ChannelRMSNorm(widths[0])
|
| 68 |
self.conv_out = nn.Conv2d(widths[0], out_ch, 3, padding=1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 71 |
x = self.conv_in(x)
|
|
@@ -73,14 +82,14 @@ class UStack(nn.Module):
|
|
| 73 |
L = len(self.down_blocks)
|
| 74 |
for i in range(L):
|
| 75 |
for blk in self.down_blocks[i]:
|
| 76 |
-
x =
|
| 77 |
if i < L - 1:
|
| 78 |
skips.append(x)
|
| 79 |
x = self.downs[i](F.pixel_unshuffle(x, 2))
|
| 80 |
for i in reversed(range(L - 1)):
|
| 81 |
x = F.pixel_shuffle(self.ups[i](x), 2) + skips[i]
|
| 82 |
for blk in self.up_blocks[i]:
|
| 83 |
-
x =
|
| 84 |
return self.conv_out(F.silu(self.norm_out(x)))
|
| 85 |
|
| 86 |
|
|
@@ -88,6 +97,8 @@ class PrimalVAE(ModelMixin, ConfigMixin):
|
|
| 88 |
"""Primal VAE: `encode` -> [B, latent_channels, H/compression, W/compression] (~N(0,1)), `decode` back to
|
| 89 |
[B, 3, H, W] in [-1, 1]. No posterior, no scaling/shift factor."""
|
| 90 |
|
|
|
|
|
|
|
| 91 |
@register_to_config
|
| 92 |
def __init__(
|
| 93 |
self,
|
|
|
|
| 15 |
import torch
|
| 16 |
import torch.nn as nn
|
| 17 |
import torch.nn.functional as F
|
| 18 |
+
import torch.utils.checkpoint
|
| 19 |
from diffusers.configuration_utils import ConfigMixin, register_to_config
|
| 20 |
from diffusers.models.modeling_utils import ModelMixin
|
| 21 |
from huggingface_hub import hf_hub_download
|
|
|
|
| 67 |
self.up_blocks = nn.ModuleList([nn.ModuleList([ResBlock(widths[i], DILATION_CYCLE[j % len(DILATION_CYCLE)]) for j in range(up_depths[i])]) for i in range(L - 1)])
|
| 68 |
self.norm_out = ChannelRMSNorm(widths[0])
|
| 69 |
self.conv_out = nn.Conv2d(widths[0], out_ch, 3, padding=1)
|
| 70 |
+
# set by ModelMixin.enable_gradient_checkpointing(); per ResBlock, only while grad is enabled
|
| 71 |
+
self.gradient_checkpointing = False
|
| 72 |
+
self._gradient_checkpointing_func = lambda blk, x: torch.utils.checkpoint.checkpoint(blk, x, use_reentrant=False)
|
| 73 |
+
|
| 74 |
+
def _block(self, blk: ResBlock, x: torch.Tensor) -> torch.Tensor:
|
| 75 |
+
if self.gradient_checkpointing and torch.is_grad_enabled():
|
| 76 |
+
return self._gradient_checkpointing_func(blk, x)
|
| 77 |
+
return blk(x)
|
| 78 |
|
| 79 |
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 80 |
x = self.conv_in(x)
|
|
|
|
| 82 |
L = len(self.down_blocks)
|
| 83 |
for i in range(L):
|
| 84 |
for blk in self.down_blocks[i]:
|
| 85 |
+
x = self._block(blk, x)
|
| 86 |
if i < L - 1:
|
| 87 |
skips.append(x)
|
| 88 |
x = self.downs[i](F.pixel_unshuffle(x, 2))
|
| 89 |
for i in reversed(range(L - 1)):
|
| 90 |
x = F.pixel_shuffle(self.ups[i](x), 2) + skips[i]
|
| 91 |
for blk in self.up_blocks[i]:
|
| 92 |
+
x = self._block(blk, x)
|
| 93 |
return self.conv_out(F.silu(self.norm_out(x)))
|
| 94 |
|
| 95 |
|
|
|
|
| 97 |
"""Primal VAE: `encode` -> [B, latent_channels, H/compression, W/compression] (~N(0,1)), `decode` back to
|
| 98 |
[B, 3, H, W] in [-1, 1]. No posterior, no scaling/shift factor."""
|
| 99 |
|
| 100 |
+
_supports_gradient_checkpointing = True
|
| 101 |
+
|
| 102 |
@register_to_config
|
| 103 |
def __init__(
|
| 104 |
self,
|