Download native/misc.py from gatilin/showo2_1_5b_visual_flow_components: direct link, hf CLI and curl.
- Browser
- Download file 16.3 kB
-
https://huggingface.co/gatilin/showo2_1_5b_visual_flow_components/resolve/main/native/misc.py
- Command line
-
hf download hf://gatilin/showo2_1_5b_visual_flow_components/native/misc.py
-
curl -L -o misc.py https://huggingface.co/gatilin/showo2_1_5b_visual_flow_components/resolve/main/native/misc.py
16.3 kB
| import torch | |
| import torch.nn as nn | |
| import torch.nn.functional as F | |
| import math | |
| from .modules import modulate, RMSNorm | |
| from timm.layers.helpers import to_2tuple | |
| from transformers import AutoTokenizer | |
| def next_token_prediction(logits, labels, vocab_szie): | |
| return F.cross_entropy(logits[:, :-1].contiguous().view(-1, vocab_szie), labels[:, 1:].contiguous().view(-1), | |
| ignore_index=-100) | |
| def velocity_prediction(latents, labels, mask=None): | |
| if mask is not None: | |
| loss = F.mse_loss(latents, labels, reduction='none')[mask.bool()] | |
| return loss.mean() | |
| else: | |
| return F.mse_loss(latents, labels) | |
| def prepare_gen_input(prompts, text_tokenizer, num_image_tokens, bos_id, eos_id, boi_id, eoi_id, pad_id, img_pad_id, | |
| max_text_len, device): | |
| batch_text_tokens = [] | |
| batch_modality_positions = [] | |
| batch_text_tokens_null = [] | |
| batch_modality_positions_null = [] | |
| for prompt in prompts: | |
| text_tokens = text_tokenizer(prompt, add_special_tokens=False)['input_ids'][:(max_text_len)] | |
| modality_positions = torch.tensor([len(text_tokens) + 1 + 1, num_image_tokens]).unsqueeze(0) | |
| text_tokens = [bos_id] + text_tokens + [boi_id] + [img_pad_id] * num_image_tokens + \ | |
| [eoi_id] + [eos_id] + [pad_id] * (max_text_len - len(text_tokens)) | |
| batch_text_tokens.append(torch.tensor(text_tokens)) | |
| batch_modality_positions.append(modality_positions) | |
| text_tokens_null = [] | |
| modality_positions_null = torch.tensor([len(text_tokens_null) + 1 + 1, num_image_tokens]).unsqueeze(0) | |
| text_tokens_null = [bos_id] + text_tokens_null + [boi_id] + [img_pad_id] * num_image_tokens + \ | |
| [eoi_id] + [eos_id] + [pad_id] * (max_text_len - len(text_tokens_null)) | |
| batch_text_tokens_null.append(torch.tensor(text_tokens_null)) | |
| batch_modality_positions_null.append(modality_positions_null) | |
| batch_text_tokens = torch.stack(batch_text_tokens, dim=0).to(device) | |
| batch_modality_positions = torch.stack(batch_modality_positions, dim=0).to(device) | |
| batch_text_tokens_null = torch.stack(batch_text_tokens_null, dim=0).to(device) | |
| batch_modality_positions_null = torch.stack(batch_modality_positions_null, dim=0).to(device) | |
| return batch_text_tokens, batch_text_tokens_null, batch_modality_positions, batch_modality_positions_null | |
| def prepare_mixed_modal_gen_input(prompts, nulls, text_tokenizer, num_image_tokens, bos_id, boi_id, eoi_id, pad_id, img_pad_id, device): | |
| batch_text_tokens = [] | |
| batch_modality_positions = [] | |
| batch_text_tokens_null = [] | |
| batch_modality_positions_null = [] | |
| for prompt, null in zip(prompts, nulls): | |
| text_tokens = text_tokenizer(prompt, add_special_tokens=False).input_ids | |
| modality_positions = torch.tensor([len(text_tokens) + 1 + 1, num_image_tokens]).unsqueeze(0) | |
| text_tokens = [bos_id] + text_tokens + [boi_id] + [img_pad_id] * num_image_tokens + [eoi_id] | |
| text_tokens_null = text_tokenizer(null, add_special_tokens=False).input_ids | |
| modality_positions_null = torch.tensor([len(text_tokens_null) + 1 + 1, num_image_tokens]).unsqueeze(0) | |
| text_tokens_null = [bos_id] + text_tokens_null + [boi_id] + [img_pad_id] * num_image_tokens + [eoi_id] | |
| len_a = len(text_tokens) | |
| len_b = len(text_tokens_null) | |
| max_len = max(len_a, len_b) | |
| if max_len % 128 != 0: | |
| max_len = (max_len // 128 + 1) * 128 | |
| num_pads_a = max_len - len_a | |
| num_pads_b = max_len - len_b | |
| text_tokens = text_tokens + [pad_id] * num_pads_a | |
| text_tokens_null = text_tokens_null + [pad_id] * num_pads_b | |
| batch_text_tokens.append(torch.tensor(text_tokens)) | |
| batch_modality_positions.append(modality_positions) | |
| batch_text_tokens_null.append(torch.tensor(text_tokens_null)) | |
| batch_modality_positions_null.append(modality_positions_null) | |
| batch_text_tokens = torch.stack(batch_text_tokens, dim=0).to(device) | |
| batch_modality_positions = torch.stack(batch_modality_positions, dim=0).to(device) | |
| batch_text_tokens_null = torch.stack(batch_text_tokens_null, dim=0).to(device) | |
| batch_modality_positions_null = torch.stack(batch_modality_positions_null, dim=0).to(device) | |
| return batch_text_tokens, batch_text_tokens_null, batch_modality_positions, batch_modality_positions_null | |
| # def prepare_mixed_modal_gen_input(prompt, text_tokenizer, num_image_tokens, boi_id, eoi_id, img_pad_id, pad_id, device): | |
| # text_tokens = text_tokenizer(prompt, add_special_tokens=False).input_ids | |
| # | |
| # modality_positions = torch.Tensor([[len(text_tokens), num_image_tokens]]).long().unsqueeze(0) | |
| # text_tokens = text_tokens + [img_pad_id] * num_image_tokens + [eoi_id] | |
| # | |
| # modality_positions_null = torch.Tensor([[2, num_image_tokens]]).long().unsqueeze(0) | |
| # text_tokens_null = [text_tokens[0]] + [boi_id] + [img_pad_id] * num_image_tokens + [eoi_id] | |
| # | |
| # len_a = len(text_tokens) | |
| # len_b = len(text_tokens_null) | |
| # num_pads_a = max(len_a, len_b) - len_a | |
| # num_pads_b = max(len_a, len_b) - len_b | |
| # | |
| # text_tokens += [pad_id] * num_pads_a | |
| # text_tokens_null += [pad_id] * num_pads_b | |
| # | |
| # text_tokens = torch.tensor(text_tokens).unsqueeze(0) | |
| # text_tokens_null = torch.tensor(text_tokens_null).unsqueeze(0) | |
| # | |
| # return text_tokens.to(device), text_tokens_null.to(device), \ | |
| # modality_positions.to(device), modality_positions_null.to(device) | |
| class PatchEmbed(nn.Module): | |
| """2D Image to Patch Embedding""" | |
| def __init__( | |
| self, | |
| patch_size=16, | |
| in_chans=3, | |
| embed_dim=768, | |
| kernel_size=None, | |
| padding=0, | |
| norm_layer=None, | |
| flatten=True, | |
| bias=True, | |
| ): | |
| super().__init__() | |
| kernel_size = kernel_size or patch_size | |
| patch_size = to_2tuple(patch_size) | |
| self.patch_size = patch_size | |
| self.flatten = flatten | |
| self.proj = nn.Conv2d( | |
| in_chans, embed_dim, kernel_size=kernel_size, stride=patch_size, bias=bias | |
| ) | |
| self.norm = norm_layer(embed_dim) if norm_layer else nn.Identity() | |
| def forward(self, x): | |
| x = self.proj(x) | |
| if self.flatten: | |
| x = x.flatten(2).transpose(1, 2) # BCHW -> BNC | |
| x = self.norm(x) | |
| return x | |
| class TimestepEmbedder(nn.Module): | |
| """ | |
| Embeds scalar timesteps into vector representations. | |
| """ | |
| def __init__(self, hidden_size, frequency_embedding_size=256): | |
| super().__init__() | |
| self.mlp = nn.Sequential( | |
| nn.Linear(frequency_embedding_size, hidden_size, bias=True), | |
| nn.SiLU(), | |
| nn.Linear(hidden_size, hidden_size, bias=True), | |
| ) | |
| self.frequency_embedding_size = frequency_embedding_size | |
| def timestep_embedding(t, dim, max_period=10000): | |
| """ | |
| Create sinusoidal timestep embeddings. | |
| :param t: a 1-D Tensor of N indices, one per batch element. | |
| These may be fractional. | |
| :param dim: the dimension of the output. | |
| :param max_period: controls the minimum frequency of the embeddings. | |
| :return: an (N, D) Tensor of positional embeddings. | |
| """ | |
| # https://github.com/openai/glide-text2im/blob/main/glide_text2im/nn.py | |
| half = dim // 2 | |
| freqs = torch.exp( | |
| -math.log(max_period) * torch.arange(start=0, end=half, dtype=torch.float32) / half | |
| ).to(device=t.device) | |
| args = t[:, None].float() * freqs[None] | |
| embedding = torch.cat([torch.cos(args), torch.sin(args)], dim=-1) | |
| if dim % 2: | |
| embedding = torch.cat([embedding, torch.zeros_like(embedding[:, :1])], dim=-1) | |
| return embedding | |
| def forward(self, t, dtype): | |
| t_freq = self.timestep_embedding(t, self.frequency_embedding_size).to(dtype) | |
| t_emb = self.mlp(t_freq) | |
| return t_emb | |
| class FinalLayer(nn.Module): | |
| """ | |
| The final layer of DiT. | |
| """ | |
| def __init__(self, hidden_size, patch_size, out_channels): | |
| super().__init__() | |
| self.norm_final = RMSNorm(hidden_size) | |
| self.linear = nn.Linear(hidden_size, patch_size * patch_size * out_channels, bias=True) | |
| self.adaLN_modulation = nn.Sequential( | |
| nn.SiLU(), | |
| nn.Linear(hidden_size, 2 * hidden_size, bias=True) | |
| ) | |
| def forward(self, x, adaln_input): | |
| shift, scale = self.adaLN_modulation(adaln_input).chunk(2, dim=1) | |
| x = modulate(self.norm_final(x), shift, scale) | |
| x = self.linear(x) | |
| return x | |
| class UpdatedVisionTransformer(nn.Module): | |
| def __init__(self, model, del_last_layer=True): | |
| super().__init__() | |
| self.model = model | |
| if del_last_layer: | |
| del self.model.transformer.resblocks[-1] | |
| def forward(self, x: torch.Tensor): | |
| x = self.model.conv1(x) # shape = [*, width, grid, grid] | |
| x = x.reshape(x.shape[0], x.shape[1], -1) # shape = [*, width, grid ** 2] | |
| x = x.permute(0, 2, 1) # shape = [*, grid ** 2, width] | |
| x = torch.cat([self.model.class_embedding.to(x.dtype) + torch.zeros(x.shape[0], 1, x.shape[-1], dtype=x.dtype, | |
| device=x.device), x], | |
| dim=1) # shape = [*, grid ** 2 + 1, width] | |
| x = x + self.model.positional_embedding.to(x.dtype) | |
| x = self.model.ln_pre(x) | |
| x = x.permute(1, 0, 2) # NLD -> LND | |
| x = self.model.transformer(x) | |
| x = x.permute(1, 0, 2)[:, 1:] # LND -> NLD | |
| return x | |
| class CLIPVisionEncoder(nn.Module): | |
| def __init__(self, model, del_last_layer=False): | |
| super().__init__() | |
| self.model = model | |
| if del_last_layer: | |
| del self.model.transformer.resblocks[-1] | |
| def forward(self, x: torch.Tensor): | |
| x = self.model.conv1(x) # shape = [*, width, grid, grid] | |
| x = x.reshape(x.shape[0], x.shape[1], -1) # shape = [*, width, grid ** 2] | |
| x = x.permute(0, 2, 1) # shape = [*, grid ** 2, width] | |
| x = torch.cat([self.model.class_embedding.to(x.dtype) + torch.zeros(x.shape[0], 1, x.shape[-1], dtype=x.dtype, | |
| device=x.device), x], | |
| dim=1) # shape = [*, grid ** 2 + 1, width] | |
| x = x + self.model.positional_embedding.to(x.dtype) | |
| x = self.model.ln_pre(x) | |
| x = x.permute(1, 0, 2) # NLD -> LND | |
| x = self.model.transformer(x) | |
| x = x.permute(1, 0, 2)[:, 1:] # LND -> NLD | |
| return x | |
| class SigLipVisionEncoder(nn.Module): | |
| def __init__(self, model, del_last_layer=True): | |
| """ | |
| A wrapper for extracting features from the penultimate layer of a vision transformer model. | |
| Args: | |
| model: The pre-trained model (e.g., CLIP or SigLIP). | |
| del_last_layer (bool): Whether to delete the last layer of the vision transformer. | |
| """ | |
| super().__init__() | |
| self.model = model | |
| # Remove the text model (if not needed) | |
| if hasattr(self.model, "text_model"): | |
| del self.model.text_model | |
| # Remove the last layer of the vision transformer | |
| if del_last_layer and hasattr(self.model.vision_model, "encoder"): | |
| del self.model.vision_model.encoder.layers[-1] | |
| # Replace the classification head (if it exists) with an identity layer | |
| if hasattr(self.model.vision_model, "head"): | |
| self.model.vision_model.head = nn.Identity() | |
| if hasattr(self.model.vision_model, "post_layernorm"): | |
| self.model.vision_model.post_layernorm = nn.Identity() | |
| def forward(self, x): | |
| """ | |
| Forward pass to extract features from the penultimate layer. | |
| Args: | |
| x: Input image tensor (pixel values). | |
| Returns: | |
| Tensor: Features from the penultimate layer. | |
| """ | |
| return self.model.get_image_features(pixel_values=x) | |
| from transformers.utils import torch_int | |
| def interpolate_pos_encoding(dim: int, position_embedding: torch.nn.Embedding, height: int, width: int, | |
| patch_size: int) -> torch.Tensor: | |
| """ | |
| This method allows to interpolate the pre-trained position encodings, to be able to use the model on higher resolution | |
| images. This method is also adapted to support torch.jit tracing and no class embeddings. | |
| Adapted from: | |
| - https://github.com/facebookresearch/dino/blob/de9ee3df6cf39fac952ab558447af1fa1365362a/vision_transformer.py#L174-L194, and | |
| - https://github.com/facebookresearch/dinov2/blob/e1277af2ba9496fbadf7aec6eba56e8d882d1e35/dinov2/models/vision_transformer.py#L179-L211 | |
| """ | |
| num_positions = position_embedding.weight.shape[0] | |
| patch_pos_embed = position_embedding.weight.unsqueeze(0) | |
| new_height = height // patch_size | |
| new_width = width // patch_size | |
| sqrt_num_positions = torch_int(num_positions**0.5) | |
| patch_pos_embed = patch_pos_embed.reshape(1, sqrt_num_positions, sqrt_num_positions, dim) | |
| patch_pos_embed = patch_pos_embed.permute(0, 3, 1, 2) | |
| patch_pos_embed = nn.functional.interpolate( | |
| patch_pos_embed, | |
| size=(new_height, new_width), | |
| mode="bicubic", | |
| align_corners=False, | |
| ) | |
| patch_pos_embed = patch_pos_embed.permute(0, 2, 3, 1).view(1, -1, dim) | |
| return patch_pos_embed | |
| def get_text_tokenizer(model_path, add_showo_tokens=True, return_showo_token_ids=False, llm_name="qwen2_5"): | |
| text_tokenizer = AutoTokenizer.from_pretrained(model_path) | |
| text_tokenizer.add_special_tokens({'pad_token': '[PAD]'}) | |
| if add_showo_tokens: | |
| if llm_name == "llama3": | |
| text_tokenizer.add_tokens('<|img_start|>') | |
| text_tokenizer.add_tokens('<|img_end|>') | |
| text_tokenizer.add_tokens('<|image_pad|>') | |
| text_tokenizer.add_tokens('<|video_pad|>') | |
| text_tokenizer.add_tokens('<|vid_start|>') | |
| text_tokenizer.add_tokens('<|vid_end|>') | |
| text_tokenizer.add_tokens('<image>') | |
| elif llm_name == "qwen2_5": | |
| text_tokenizer.add_tokens('<image>') | |
| text_tokenizer.add_tokens('<|vid_start|>') | |
| text_tokenizer.add_tokens('<|vid_end|>') | |
| else: | |
| raise NotImplementedError | |
| if return_showo_token_ids: | |
| if llm_name == "llama3": | |
| showo_token_ids = { | |
| "bos_id": text_tokenizer.get_vocab()["<|begin_of_text|>"], | |
| "eos_id": text_tokenizer.eos_token_id, | |
| "boi_id": text_tokenizer.get_vocab()["<|img_start|>"], | |
| "eoi_id": text_tokenizer.get_vocab()["<|img_end|>"], | |
| "bov_id": text_tokenizer.get_vocab()["<|vid_start|>"], | |
| "eov_id": text_tokenizer.get_vocab()["<|vid_end|>"], | |
| "img_pad_id": text_tokenizer.get_vocab()["<|image_pad|>"], | |
| "vid_pad_id": text_tokenizer.get_vocab()["<|video_pad|>"], | |
| "img_id": text_tokenizer.get_vocab()["<image>"], | |
| } | |
| elif llm_name == "qwen2_5": | |
| showo_token_ids = { | |
| "bos_id": text_tokenizer.get_vocab()["<|im_start|>"], | |
| "eos_id": text_tokenizer.eos_token_id, | |
| "boi_id": text_tokenizer.get_vocab()["<|vision_start|>"], | |
| "eoi_id": text_tokenizer.get_vocab()["<|vision_end|>"], | |
| "bov_id": text_tokenizer.get_vocab()["<|vid_start|>"], | |
| "eov_id": text_tokenizer.get_vocab()["<|vid_end|>"], | |
| "img_pad_id": text_tokenizer.get_vocab()["<|image_pad|>"], | |
| "vid_pad_id": text_tokenizer.get_vocab()["<|video_pad|>"], | |
| "img_id": text_tokenizer.get_vocab()["<image>"], | |
| } | |
| else: | |
| raise NotImplementedError | |
| return text_tokenizer, showo_token_ids | |
| return text_tokenizer | |
| def get_weight_type(config): | |
| if config.training.mixed_precision == 'bf16': | |
| weight_type = torch.bfloat16 | |
| elif config.training.mixed_precision == 'float16': | |
| weight_type = torch.float16 | |
| else: | |
| weight_type = torch.float32 | |
| return weight_type | |