Download methods/prunning/SiTo/patch.py from doanh25032004/video_gen_physics_backup: direct link, hf CLI and curl.
- Browser
- Download file 9.24 kB
-
https://huggingface.co/doanh25032004/video_gen_physics_backup/resolve/main/methods/prunning/SiTo/patch.py
- Command line
-
hf download hf://doanh25032004/video_gen_physics_backup/methods/prunning/SiTo/patch.py
-
curl -L -o patch.py https://huggingface.co/doanh25032004/video_gen_physics_backup/resolve/main/methods/prunning/SiTo/patch.py
9.24 kB
| import torch | |
| import math | |
| from typing import Type, Dict, Any, Tuple, Callable | |
| import copy | |
| from . import sito | |
| from .utils import isinstance_str, init_generator | |
| import torch.nn.functional as F | |
| import time | |
| def select_sito_method(x: torch.Tensor, sito_info: Dict[str, Any]) -> Tuple[Callable, ...]: | |
| args = sito_info["args"] | |
| current_timestep = sito_info["timestep"] | |
| original_h, original_w = sito_info["size"] # 64,64 | |
| original_tokens = original_h * original_w | |
| downsaple_ratio = int(math.ceil(math.sqrt(original_tokens // x.shape[1]))) | |
| if (downsaple_ratio <= args["max_downsample_ratio"]): | |
| w = int(math.ceil(original_w / downsaple_ratio)) | |
| h = int(math.ceil(original_h / downsaple_ratio)) | |
| num_prune = int(x.shape[1] * args["prune_ratio"]) | |
| p, r = sito.prune_and_recover_tokens(x, num_prune, w=w, h=h, sx=args['sx'], sy=args['sy'],noise_alpha=args['noise_alpha'],sim_beta=args['sim_beta'],current_timestep=current_timestep) | |
| else: | |
| p, r = (sito.do_nothing, sito.do_nothing) | |
| p_a, r_a = (p, r) if args["prune_selfattn_flag"] else (sito.do_nothing, sito.do_nothing) | |
| p_c, r_c = (p, r) if args["prune_crossattn_flag"] else (sito.do_nothing, sito.do_nothing) | |
| p_m, r_m = (p, r) if args["prune_mlp_flag"] else (sito.do_nothing, sito.do_nothing) | |
| return p_a, p_c, p_m, r_a, r_c, r_m | |
| def make_sito_block(block_class: Type[torch.nn.Module]) -> Type[torch.nn.Module]: | |
| class sitoBlock(block_class): | |
| _parent = block_class | |
| def _forward(self, x: torch.Tensor, context: torch.Tensor = None) -> torch.Tensor: | |
| p_a, p_c, p_m, r_a, r_c, r_m = select_sito_method(x, self._sito_info) # 选择方法 | |
| # self-attention | |
| prune_x = p_a(self.norm1(x)) | |
| out1 = self.attn1(prune_x, context=context if self.disable_self_attn else None) | |
| x = r_a(out1) + x | |
| # cross-attention | |
| prop_x = p_c(self.norm2(x)) | |
| out2= self.attn2(prop_x, context=context) | |
| x = r_c(out2) + x | |
| # MLP | |
| x = r_m(self.ff(p_m(self.norm3(x)))) + x | |
| return x | |
| return sitoBlock | |
| def make_diffusers_sito_block(block_class: Type[torch.nn.Module]) -> Type[torch.nn.Module]: | |
| """ | |
| Make a patched class for a diffusers model. | |
| This patch applies ToMe to the forward function of the block. | |
| """ | |
| class sitoBlock(block_class): | |
| # Save for unpatching later | |
| _parent = block_class | |
| def forward( | |
| self, | |
| hidden_states, | |
| attention_mask=None, | |
| encoder_hidden_states=None, | |
| encoder_attention_mask=None, | |
| timestep=None, | |
| cross_attention_kwargs=None, | |
| class_labels=None, | |
| ) -> torch.Tensor: | |
| # (1) sito | |
| p_a, p_c, p_m, r_a, r_c, r_m = select_sito_method(hidden_states, self._sito_info) | |
| if self.use_ada_layer_norm: | |
| norm_hidden_states = self.norm1(hidden_states, timestep) | |
| elif self.use_ada_layer_norm_zero: | |
| norm_hidden_states, gate_msa, shift_mlp, scale_mlp, gate_mlp = self.norm1( | |
| hidden_states, timestep, class_labels, hidden_dtype=hidden_states.dtype | |
| ) | |
| else: | |
| norm_hidden_states = self.norm1(hidden_states) | |
| # (2) sito p_a | |
| norm_hidden_states = p_a(norm_hidden_states) | |
| # 1. Self-Attention | |
| cross_attention_kwargs = cross_attention_kwargs if cross_attention_kwargs is not None else {} | |
| attn_output = self.attn1( | |
| norm_hidden_states, | |
| encoder_hidden_states=encoder_hidden_states if self.only_cross_attention else None, | |
| attention_mask=attention_mask, | |
| **cross_attention_kwargs, | |
| ) | |
| if self.use_ada_layer_norm_zero: | |
| attn_output = gate_msa.unsqueeze(1) * attn_output | |
| # (3) sito r_a | |
| hidden_states = r_a(attn_output) + hidden_states | |
| if self.attn2 is not None: | |
| norm_hidden_states = ( | |
| self.norm2(hidden_states, timestep) if self.use_ada_layer_norm else self.norm2(hidden_states) | |
| ) | |
| # (4) sito p_c | |
| norm_hidden_states = p_c(norm_hidden_states) | |
| # 2. Cross-Attention | |
| attn_output = self.attn2( | |
| norm_hidden_states, | |
| encoder_hidden_states=encoder_hidden_states, | |
| attention_mask=encoder_attention_mask, | |
| **cross_attention_kwargs, | |
| ) | |
| # (5) sito r_c | |
| hidden_states = r_c(attn_output) + hidden_states | |
| # 3. Feed-forward | |
| norm_hidden_states = self.norm3(hidden_states) | |
| if self.use_ada_layer_norm_zero: | |
| norm_hidden_states = norm_hidden_states * (1 + scale_mlp[:, None]) + shift_mlp[:, None] | |
| # (6) sito p_m | |
| norm_hidden_states = p_m(norm_hidden_states) | |
| ff_output = self.ff(norm_hidden_states) | |
| if self.use_ada_layer_norm_zero: | |
| ff_output = gate_mlp.unsqueeze(1) * ff_output | |
| # (7) sito r_m | |
| hidden_states = r_m(ff_output) + hidden_states | |
| return hidden_states | |
| return sitoBlock | |
| def hook_sito_model(model: torch.nn.Module): | |
| def hook(module, args): | |
| module._sito_info["size"] = (args[0].shape[2], args[0].shape[3]) | |
| module._sito_info["timestep"] = args[1][0].cpu().item() | |
| return None | |
| model._sito_info["hooks"].append(model.register_forward_pre_hook(hook)) | |
| def apply_patch( | |
| model: torch.nn.Module, | |
| prune_ratio: int = 0.5, | |
| max_downsample_ratio: int = 1, | |
| prune_selfattn_flag: bool = True, | |
| prune_crossattn_flag: bool = False, | |
| prune_mlp_flag: bool = False, | |
| sx: int = 2, sy: int = 2, | |
| noise_alpha:float = 0.1, | |
| sim_beta:float = 1 | |
| ): | |
| remove_patch(model) | |
| is_diffusers = isinstance_str(model, "DiffusionPipeline") or isinstance_str(model, "ModelMixin") | |
| if not is_diffusers: | |
| if not hasattr(model, "model") or not hasattr(model.model, "diffusion_model"): | |
| raise RuntimeError("Provided model was not a Stable Diffusion / Latent Diffusion model, as expected.") | |
| diffusion_model = model.model.diffusion_model | |
| else: | |
| diffusion_model = model.unet if hasattr(model, "unet") else model | |
| diffusion_model._sito_info = { | |
| "name": None, | |
| "size": None, | |
| "timestep": None, | |
| "hooks": [], | |
| "args": { | |
| "prune_selfattn_flag": prune_selfattn_flag, | |
| "prune_crossattn_flag": prune_crossattn_flag, | |
| "prune_mlp_flag": prune_mlp_flag, | |
| "prune_ratio": prune_ratio, | |
| "max_downsample_ratio": max_downsample_ratio, | |
| "sx": sx, "sy": sy, | |
| "noise_alpha":noise_alpha, | |
| "sim_beta":sim_beta | |
| } | |
| } | |
| hook_sito_model(diffusion_model) # 添加size属性 | |
| for x, module in diffusion_model.named_modules(): | |
| if isinstance_str(module, "BasicTransformerBlock"): | |
| make_sito_block_fn = make_diffusers_sito_block if is_diffusers else make_sito_block | |
| module.__class__ = make_sito_block_fn( | |
| module.__class__) | |
| module._sito_info = diffusion_model._sito_info | |
| module._myname = x | |
| if not hasattr(module, "disable_self_attn") and not is_diffusers: | |
| module.disable_self_attn = False | |
| if not hasattr(module, "use_ada_layer_norm_zero") and is_diffusers: | |
| module.use_ada_layer_norm = False | |
| module.use_ada_layer_norm_zero = False | |
| return model | |
| def remove_patch(model: torch.nn.Module): | |
| """ Removes a patch from a sito Diffusion module if it was already patched. """ | |
| model = model.unet if hasattr(model, "unet") else model | |
| for _, module in model.named_modules(): | |
| if hasattr(module, "_sito_info"): | |
| for hook in module._sito_info["hooks"]: | |
| hook.remove() | |
| module._sito_info["hooks"].clear() | |
| if module.__class__.__name__ == "sitoBlock": | |
| module.__class__ = module._parent | |
| return model | |
| ''' | |
| Unet Name | |
| input_blocks.1.1.transformer_blocks.0 | |
| input_blocks.2.1.transformer_blocks.0 | |
| input_blocks.4.1.transformer_blocks.0 | |
| input_blocks.5.1.transformer_blocks.0 | |
| input_blocks.7.1.transformer_blocks.0 | |
| input_blocks.8.1.transformer_blocks.0 | |
| middle_block.1.transformer_blocks.0 | |
| output_blocks.3.1.transformer_blocks.0 | |
| output_blocks.4.1.transformer_blocks.0 | |
| output_blocks.5.1.transformer_blocks.0 | |
| output_blocks.6.1.transformer_blocks.0 | |
| output_blocks.7.1.transformer_blocks.0 | |
| output_blocks.8.1.transformer_blocks.0 | |
| output_blocks.9.1.transformer_blocks.0 | |
| output_blocks.10.1.transformer_blocks.0 | |
| output_blocks.11.1.transformer_blocks.0 | |
| ''' |