Image Feature Extraction
Transformers
Safetensors
skinmap
feature-extraction
dermatology
medical-imaging
embeddings
clip
custom_code
Instructions to use Digital-Dermatology/SkinMap with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Digital-Dermatology/SkinMap with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-feature-extraction", model="Digital-Dermatology/SkinMap", trust_remote_code=True)# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("Digital-Dermatology/SkinMap", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
| import collections.abc | |
| import math | |
| import warnings | |
| from enum import Enum | |
| from itertools import repeat | |
| import numpy as np | |
| import torch | |
| from torch import nn | |
| class ModelType(Enum): | |
| VIT = 0 | |
| CNN = 1 | |
| UNET = 2 | |
| def initialize_weights(*models): | |
| for model in models: | |
| for module in model.modules(): | |
| if isinstance(module, nn.Conv2d) or isinstance(module, nn.Linear): | |
| nn.init.kaiming_normal_(module.weight) | |
| if module.bias is not None: | |
| module.bias.data.zero_() | |
| elif isinstance(module, nn.BatchNorm2d): | |
| module.weight.data.fill_(1) | |
| module.bias.data.zero_() | |
| def _no_grad_trunc_normal_(tensor, mean, std, a, b): | |
| # Cut & paste from PyTorch official master until it's in a few official releases - RW | |
| # Method based on https://people.sc.fsu.edu/~jburkardt/presentations/truncated_normal.pdf | |
| def norm_cdf(x): | |
| # Computes standard normal cumulative distribution function | |
| return (1.0 + math.erf(x / math.sqrt(2.0))) / 2.0 | |
| if (mean < a - 2 * std) or (mean > b + 2 * std): | |
| warnings.warn( | |
| "mean is more than 2 std from [a, b] in nn.init.trunc_normal_. " | |
| "The distribution of values may be incorrect.", | |
| stacklevel=2, | |
| ) | |
| with torch.no_grad(): | |
| # Values are generated by using a truncated uniform distribution and | |
| # then using the inverse CDF for the normal distribution. | |
| # Get upper and lower cdf values | |
| l = norm_cdf((a - mean) / std) | |
| u = norm_cdf((b - mean) / std) | |
| # Uniformly fill tensor with values from [l, u], then translate to | |
| # [2l-1, 2u-1]. | |
| tensor.uniform_(2 * l - 1, 2 * u - 1) | |
| # Use inverse cdf transform for normal distribution to get truncated | |
| # standard normal | |
| tensor.erfinv_() | |
| # Transform to proper mean, std | |
| tensor.mul_(std * math.sqrt(2.0)) | |
| tensor.add_(mean) | |
| # Clamp to ensure it's in the proper range | |
| tensor.clamp_(min=a, max=b) | |
| return tensor | |
| def trunc_normal_(tensor, mean=0.0, std=1.0, a=-2.0, b=2.0): | |
| # type: (Tensor, float, float, float, float) -> Tensor | |
| return _no_grad_trunc_normal_(tensor, mean, std, a, b) | |
| def get_params_groups(model): | |
| regularized = [] | |
| not_regularized = [] | |
| for name, param in model.named_parameters(): | |
| if not param.requires_grad: | |
| continue | |
| # we do not regularize biases nor Norm parameters | |
| if name.endswith(".bias") or len(param.shape) == 1: | |
| not_regularized.append(param) | |
| else: | |
| regularized.append(param) | |
| return [{"params": regularized}, {"params": not_regularized, "weight_decay": 0.0}] | |
| def cosine_scheduler( | |
| base_value, | |
| final_value, | |
| epochs, | |
| niter_per_ep, | |
| warmup_epochs=0, | |
| start_warmup_value=0, | |
| ): | |
| warmup_schedule = np.array([]) | |
| warmup_iters = warmup_epochs * niter_per_ep | |
| if warmup_epochs > 0: | |
| warmup_schedule = np.linspace(start_warmup_value, base_value, warmup_iters) | |
| iters = np.arange(epochs * niter_per_ep - warmup_iters) | |
| schedule = final_value + 0.5 * (base_value - final_value) * ( | |
| 1 + np.cos(np.pi * iters / len(iters)) | |
| ) | |
| schedule = np.concatenate((warmup_schedule, schedule)) | |
| assert len(schedule) == epochs * niter_per_ep | |
| return schedule | |
| def cancel_gradients_last_layer(epoch, model, freeze_last_layer): | |
| if epoch >= freeze_last_layer: | |
| return | |
| for n, p in model.named_parameters(): | |
| if "last_layer" in n: | |
| p.grad = None | |
| def drop_path(x, drop_prob: float = 0.0, training: bool = False): | |
| if drop_prob == 0.0 or not training: | |
| return x | |
| keep_prob = 1 - drop_prob | |
| # work with diff dim tensors, not just 2D ConvNets | |
| shape = (x.shape[0],) + (1,) * (x.ndim - 1) | |
| random_tensor = keep_prob + torch.rand(shape, dtype=x.dtype, device=x.device) | |
| random_tensor.floor_() # binarize | |
| output = x.div(keep_prob) * random_tensor | |
| return output | |
| class DropPath(nn.Module): | |
| """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks).""" | |
| def __init__(self, drop_prob=None): | |
| super(DropPath, self).__init__() | |
| self.drop_prob = drop_prob | |
| def forward(self, x): | |
| return drop_path(x, self.drop_prob, self.training) | |
| # From PyTorch internals | |
| def _ntuple(n): | |
| def parse(x): | |
| if isinstance(x, collections.abc.Iterable) and not isinstance(x, str): | |
| return x | |
| return tuple(repeat(x, n)) | |
| return parse | |
| to_1tuple = _ntuple(1) | |
| to_2tuple = _ntuple(2) | |
| to_3tuple = _ntuple(3) | |
| to_4tuple = _ntuple(4) | |
| to_ntuple = _ntuple | |
| def ema_update_teacher(student, teacher, momentum_schedule, n_iter): | |
| # EMA update for the teacher | |
| with torch.no_grad(): | |
| # momentum parameter | |
| m = momentum_schedule[n_iter] | |
| names_q, params_s, names_k, params_t = [], [], [], [] | |
| # get student parameters | |
| for name_s, param_s in student.named_parameters(): | |
| names_q.append(name_s) | |
| params_s.append(param_s) | |
| # get teacher parameters | |
| for name_t, param_t in teacher.named_parameters(): | |
| names_k.append(name_t) | |
| params_t.append(param_t) | |
| # get the names (parameters) which both have in common | |
| names_common = list(set(names_q) & set(names_k)) | |
| params_s = [ | |
| param_s | |
| for name_s, param_s in zip(names_q, params_s) | |
| if name_s in names_common | |
| ] | |
| params_t = [ | |
| param_t | |
| for name_t, param_t in zip(names_k, params_t) | |
| if name_t in names_common | |
| ] | |
| for param_s, param_t in zip(params_s, params_t): | |
| param_t.data.mul_(m).add_((1 - m) * param_s.detach().data) | |
| # -------------------------------------------------------- | |
| # 2D sine-cosine position embedding | |
| # References: | |
| # Transformer: https://github.com/tensorflow/models/blob/master/official/nlp/transformer/model_utils.py | |
| # MoCo v3: https://github.com/facebookresearch/moco-v3 | |
| # -------------------------------------------------------- | |
| def get_2d_sincos_pos_embed(embed_dim, grid_size, cls_token=False): | |
| """ | |
| grid_size: int of the grid height and width | |
| return: | |
| pos_embed: [grid_size*grid_size, embed_dim] or [1+grid_size*grid_size, embed_dim] (w/ or w/o cls_token) | |
| """ | |
| grid_h = np.arange(grid_size, dtype=np.float32) | |
| grid_w = np.arange(grid_size, dtype=np.float32) | |
| grid = np.meshgrid(grid_w, grid_h) # here w goes first | |
| grid = np.stack(grid, axis=0) | |
| grid = grid.reshape([2, 1, grid_size, grid_size]) | |
| pos_embed = get_2d_sincos_pos_embed_from_grid(embed_dim, grid) | |
| if cls_token: | |
| pos_embed = np.concatenate([np.zeros([1, embed_dim]), pos_embed], axis=0) | |
| return pos_embed | |
| def get_2d_sincos_pos_embed_from_grid(embed_dim, grid): | |
| assert embed_dim % 2 == 0 | |
| # use half of dimensions to encode grid_h | |
| emb_h = get_1d_sincos_pos_embed_from_grid(embed_dim // 2, grid[0]) # (H*W, D/2) | |
| emb_w = get_1d_sincos_pos_embed_from_grid(embed_dim // 2, grid[1]) # (H*W, D/2) | |
| emb = np.concatenate([emb_h, emb_w], axis=1) # (H*W, D) | |
| return emb | |
| def get_1d_sincos_pos_embed_from_grid(embed_dim, pos): | |
| """ | |
| embed_dim: output dimension for each position | |
| pos: a list of positions to be encoded: size (M,) | |
| out: (M, D) | |
| """ | |
| assert embed_dim % 2 == 0 | |
| omega = np.arange(embed_dim // 2, dtype=np.float32) | |
| omega /= embed_dim / 2.0 | |
| omega = 1.0 / 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 | |