Download utils/common.py from poet70/vla-sft-code-motus: direct link, hf CLI and curl.
- Browser
- Download file 6.18 kB
-
https://huggingface.co/poet70/vla-sft-code-motus/resolve/main/utils/common.py
- Command line
-
hf download hf://poet70/vla-sft-code-motus/utils/common.py
-
curl -L -o common.py https://huggingface.co/poet70/vla-sft-code-motus/resolve/main/utils/common.py
6.18 kB
| from contextlib import contextmanager | |
| import gc | |
| import time | |
| import math | |
| from pathlib import Path | |
| import torch | |
| import deepspeed.comm.comm as dist | |
| import imageio | |
| from safetensors import safe_open | |
| import numpy as np | |
| DTYPE_MAP = { | |
| 'float32': torch.float32, | |
| 'float16': torch.float16, | |
| 'bfloat16': torch.bfloat16, | |
| 'float8': torch.float8_e4m3fn, | |
| 'float8_e4m3fn': torch.float8_e4m3fn, | |
| 'float8_e5m2': torch.float8_e5m2, | |
| } | |
| VIDEO_EXTENSIONS = set() | |
| for x in imageio.config.video_extensions: | |
| VIDEO_EXTENSIONS.add(x.extension) | |
| VIDEO_EXTENSIONS.add(x.extension.upper()) | |
| AUTOCAST_DTYPE = None | |
| def get_rank(): | |
| return dist.get_rank() | |
| def is_main_process(): | |
| return get_rank() == 0 | |
| def zero_first(): | |
| if not is_main_process(): | |
| dist.barrier() | |
| yield | |
| if is_main_process(): | |
| dist.barrier() | |
| def empty_cuda_cache(): | |
| gc.collect() | |
| torch.cuda.empty_cache() | |
| def log_duration(name): | |
| start = time.time() | |
| try: | |
| yield | |
| finally: | |
| print(f'{name}: {time.time()-start:.3f}') | |
| def load_safetensors(path): | |
| tensors = {} | |
| with safe_open(path, framework="pt", device="cpu") as f: | |
| for key in f.keys(): | |
| tensors[key] = f.get_tensor(key) | |
| return tensors | |
| def load_state_dict(path): | |
| path = str(path) | |
| if path.endswith('.safetensors'): | |
| sd = load_safetensors(path) | |
| else: | |
| sd = torch.load(path, weights_only=True) | |
| for key in sd: | |
| if key.endswith('scale_input') or key.endswith('scale_weight'): | |
| raise ValueError('fp8_scaled weights are not supported. Please use bf16 or normal fp8 weights.') | |
| return sd | |
| def iterate_safetensors(path): | |
| path = Path(path) | |
| if path.is_dir(): | |
| safetensors_files = list(path.glob('*.safetensors')) | |
| if len(safetensors_files) == 0: | |
| raise FileNotFoundError(f'Cound not find safetensors files in directory {path}') | |
| else: | |
| if path.suffix != '.safetensors': | |
| raise ValueError(f'Expected {path} to be a safetensors file') | |
| safetensors_files = [path] | |
| for filename in safetensors_files: | |
| with safe_open(str(filename), framework="pt", device="cpu") as f: | |
| for key in f.keys(): | |
| if key.endswith('scale_input') or key.endswith('scale_weight'): | |
| raise ValueError('fp8_scaled weights are not supported. Please use bf16 or normal fp8 weights.') | |
| yield key, f.get_tensor(key) | |
| def round_to_nearest_multiple(x, multiple): | |
| return int(round(x / multiple) * multiple) | |
| def round_down_to_multiple(x, multiple): | |
| return int((x // multiple) * multiple) | |
| def time_shift(mu: float, sigma: float, t: torch.Tensor): | |
| return math.exp(mu) / (math.exp(mu) + (1 / t - 1) ** sigma) | |
| def get_lin_function(x1: float = 256, y1: float = 0.5, x2: float = 4096, y2: float = 1.15): | |
| m = (y2 - y1) / (x2 - x1) | |
| b = y1 - m * x1 | |
| return lambda x: m * x + b | |
| def get_t_distribution(model_config): | |
| timestep_sample_method = getattr(model_config, 'timestep_sample_method', 'logit_normal') | |
| if timestep_sample_method == 'logit_normal': | |
| dist = torch.distributions.normal.Normal(0, 1) | |
| elif timestep_sample_method == 'uniform': | |
| dist = torch.distributions.uniform.Uniform(0, 1) | |
| else: | |
| raise NotImplementedError() | |
| n_buckets = 10_000 | |
| delta = 1 / n_buckets | |
| min_quantile = delta | |
| max_quantile = 1 - delta | |
| quantiles = torch.linspace(min_quantile, max_quantile, n_buckets) | |
| t = dist.icdf(quantiles) | |
| if timestep_sample_method == 'logit_normal': | |
| sigmoid_scale = getattr(model_config, 'sigmoid_scale', 1.0) | |
| t = t * sigmoid_scale | |
| t = torch.sigmoid(t) | |
| return t | |
| def slice_t_distribution(t, min_t=0.0, max_t=1.0): | |
| start = torch.searchsorted(t, min_t).item() | |
| end = torch.searchsorted(t, max_t).item() | |
| return t[start:end] | |
| def sample_t(t, batch_size, quantile=None): | |
| if quantile is not None: | |
| i = (torch.full((batch_size,), quantile) * len(t)).to(torch.int32) | |
| else: | |
| i = torch.randint(0, len(t), size=(batch_size,)) | |
| return t[i] | |
| def get_1d_sincos_pos_embed_from_grid(embed_dim: int, pos): | |
| """ | |
| Get 1D positional embedding in the form of sin and cos. | |
| Paper: | |
| https://arxiv.org/abs/1706.03762 | |
| Source: | |
| https://github.com/facebookresearch/mae/blob/main/util/pos_embed.py | |
| Args: | |
| embed_dim (int): output dimension for each position. | |
| pos (ndarray | list): a list of positions to be encoded, size (M,). | |
| Returns: | |
| out (ndarray): resulting positional embedding, size (M, D). | |
| """ | |
| assert embed_dim % 2 == 0 | |
| omega = np.arange(embed_dim // 2, dtype=np.float64) | |
| omega /= embed_dim / 2. | |
| omega = 1. / 10000**omega # (D/2,) | |
| pos = pos.reshape(-1) # (M,) | |
| out = np.einsum('m,d->md', pos, omega) # (M, D/2), outer product | |
| emb_sin = np.sin(out) # (M, D/2) | |
| emb_cos = np.cos(out) # (M, D/2) | |
| emb = np.concatenate([emb_sin, emb_cos], axis=1) # (M, D) | |
| return emb | |
| def get_nd_sincos_pos_embed_from_grid(embed_dim: int, grid_sizes): | |
| """ | |
| Get ND positional embedding from grid sizes. | |
| All dimensions are summed up for factorization. | |
| Paper: | |
| https://arxiv.org/abs/2307.06304 | |
| Args: | |
| embed_dim (int): output dimension for each position. | |
| grid_sizes (tuple): grids sizes in each dimension, length = K. | |
| If some grid size is lower than 1, we do not add any positional embedding. | |
| Returns: | |
| out (ndarray): resulting positional embedding, size (grid_sizes[0], ..., grid_sizes[K-1], D). | |
| """ | |
| # We sum up all dimensions for factorization | |
| emb = np.zeros(grid_sizes + (embed_dim,)) | |
| for size_idx, grid_size in enumerate(grid_sizes): | |
| # For grid size of 1, we do not need to add any positional embedding | |
| if grid_size <= 1: | |
| continue | |
| pos = np.arange(grid_size) | |
| posemb_shape = [1] * len(grid_sizes) + [embed_dim] | |
| posemb_shape[size_idx] = -1 | |
| emb += get_1d_sincos_pos_embed_from_grid(embed_dim, pos).reshape(posemb_shape) | |
| return emb | |