Image Classification
Transformers
PyTorch
TensorBoard
Safetensors
customManuel
Generated from Trainer
custom_code
Instructions to use Manu8/vit_cifar with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Manu8/vit_cifar with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-classification", model="Manu8/vit_cifar", trust_remote_code=True) pipe("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/hub/parrots.png")# pip install -U transformers accelerate # Load model directly from transformers import AutoModelForImageClassification model = AutoModelForImageClassification.from_pretrained("Manu8/vit_cifar", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Download model.py from Manu8/vit_cifar: direct link, hf CLI and curl.
- Browser
- Download file 7.62 kB
-
https://huggingface.co/Manu8/vit_cifar/resolve/main/model.py
- Command line
-
hf download hf://Manu8/vit_cifar/model.py
-
curl -L -o model.py https://huggingface.co/Manu8/vit_cifar/resolve/main/model.py
7.62 kB
| from .config import VITConfig | |
| from transformers import PreTrainedModel | |
| import torch | |
| from torch import nn | |
| import os | |
| from einops import rearrange,repeat | |
| from einops.layers.torch import Rearrange | |
| import numpy as np | |
| import torch.nn.functional as F | |
| class shift_patch(nn.Module): | |
| def __init__(self,patch_size=16): | |
| super().__init__() | |
| self.patch_size = patch_size // 2 | |
| def forward(self, x): | |
| bs,_, _, chanel = x.size() | |
| shifts = ((-self.patch_size, self.patch_size, -self.patch_size, self.patch_size), | |
| (self.patch_size, -self.patch_size, -self.patch_size, self.patch_size), | |
| (-self.patch_size, self.patch_size, self.patch_size, -self.patch_size), | |
| (self.patch_size, -self.patch_size, self.patch_size, -self.patch_size)) | |
| shifted_x = list(map(lambda shift: F.pad(x, shift), shifts)) | |
| return shifted_x | |
| def posemb_sincos_2d(h, w, dim, temperature: int = 10000, dtype = torch.float32): | |
| y, x = torch.meshgrid(torch.arange(h), torch.arange(w), indexing="ij") | |
| assert (dim % 4) == 0, "feature dimension must be multiple of 4 for sincos emb" | |
| omega = torch.arange(dim // 4) / (dim // 4 - 1) | |
| omega = 1.0 / (temperature ** omega) | |
| y = y.flatten()[:, None] * omega[None, :] | |
| x = x.flatten()[:, None] * omega[None, :] | |
| pe = torch.cat((x.sin(), x.cos(), y.sin(), y.cos()), dim=1) | |
| return pe.type(dtype) | |
| class patch_embedding(nn.Module): | |
| def __init__(self,height=224,width=224,n_channels=3,patch_size=16,batch_size=2,dim=512): | |
| super().__init__() | |
| assert height%patch_size==0 and width%patch_size==0 ,"Height and Width should be multiples of patch size wich is {0}".format(patch_size) | |
| #self.class_token = nn.Parameter(torch.randn(1, 1, dim)) | |
| self.pos_embedding = posemb_sincos_2d( | |
| h = height // patch_size, | |
| w = width // patch_size, | |
| dim = dim, | |
| ) | |
| self.patch_size = patch_size | |
| self.n_patchs = height*width//(patch_size**2) | |
| #self.embedding = torch.nn.Parameter(torch.randn(1,self.n_patchs+1, dim)) | |
| self.projection = nn.Sequential(nn.LayerNorm(patch_size*patch_size*n_channels*5), | |
| nn.Linear(patch_size*patch_size*n_channels*5,dim), | |
| nn.LayerNorm(dim) | |
| ) | |
| self.shift = shift_patch(patch_size=patch_size) | |
| self.patch = nn.Sequential( | |
| Rearrange("b c (h p1) (w p2) -> b (h w) (p1 p2 c)", p1 = patch_size, p2 = patch_size), | |
| ) | |
| def forward(self, x): | |
| #x bs,h,w,c | |
| embedding = self.pos_embedding.to(x.device) | |
| left_up,right_up,left_down,right_down = self.shift(x) | |
| x = torch.cat([x,left_up,right_up,left_down,right_down],dim=1) | |
| #first we resize the inputs Bs,Num_patchs,* | |
| x = self.patch(x) | |
| #projection on the dim of model | |
| x = self.projection(x) | |
| outputs = x + embedding | |
| return outputs | |
| class LocallySelfAttention(nn.Module): | |
| def __init__(self, embed_dim, num_heads): | |
| super(LocallySelfAttention, self).__init__() | |
| assert embed_dim % num_heads == 0, "Embedding dimension must be 0 modulo number of heads." | |
| self.embed_dim = embed_dim | |
| self.num_heads = num_heads | |
| self.head_dim = embed_dim // num_heads | |
| self.norm = nn.LayerNorm(embed_dim) | |
| self.tau = nn.Parameter(torch.sqrt(torch.tensor(self.head_dim))) | |
| self.qkv_proj = nn.Linear(embed_dim, 3*embed_dim,bias = False) | |
| self.o_proj = nn.Linear(embed_dim, embed_dim) | |
| self._reset_parameters() | |
| def _reset_parameters(self): | |
| # Original Transformer initialization, see PyTorch documentation | |
| nn.init.xavier_uniform_(self.qkv_proj.weight) | |
| nn.init.xavier_uniform_(self.o_proj.weight) | |
| self.o_proj.bias.data.fill_(0) | |
| def _masked_softmax(self, attention_scores, attention_mask): | |
| if attention_mask is not None: | |
| attention_scores = attention_scores.masked_fill(attention_mask, float('-inf')) | |
| return F.softmax(attention_scores, dim=-1) | |
| def forward(self,x, need_weights=True, attn_mask=None): | |
| x = self.norm(x) | |
| batch_size, seq_length, _ = x.size() | |
| qkv = self.qkv_proj(x).chunk(3, dim = -1) | |
| q, k, v = map(lambda t: rearrange(t, 'b n (h d) -> b h n d', h = self.num_heads), qkv) | |
| attention_scores = torch.matmul(q, k.transpose(-1, -2)) / self.tau | |
| attention_scores = self._masked_softmax(attention_scores, attn_mask) | |
| attention_output = torch.matmul(attention_scores, v) | |
| attention_output = rearrange(attention_output, 'b h n d -> b n (h d)') | |
| return self.o_proj(attention_output) | |
| class feedforward(nn.Module): | |
| def __init__(self,embed_dim=512,ff_hidden_dim=1024,dropout_rate = 0.1): | |
| super().__init__() | |
| self.mlp = nn.Sequential( | |
| nn.LayerNorm(embed_dim), | |
| nn.Linear(embed_dim, ff_hidden_dim), | |
| nn.GELU(), | |
| nn.Dropout(p=dropout_rate), | |
| nn.Linear(ff_hidden_dim, embed_dim), | |
| nn.GELU(), | |
| nn.Dropout(p=dropout_rate), | |
| ) | |
| def forward(self, x): | |
| outputs = self.mlp(x) | |
| return outputs | |
| class Transformer(nn.Module): | |
| def __init__(self, embed_dim=512, depth=4, heads=2, ff_hidden_dim=1024, dropout_rate = 0.1): | |
| super().__init__() | |
| self.layers = nn.ModuleList([]) | |
| for _ in range(depth): | |
| self.layers.append(nn.ModuleList([ | |
| LocallySelfAttention(embed_dim,heads), | |
| feedforward(embed_dim,ff_hidden_dim, dropout_rate) | |
| ])) | |
| def forward(self, x,mask=None): | |
| for attn, ff in self.layers: | |
| x = attn(x,attn_mask = mask) + x | |
| x = ff(x) + x | |
| return x | |
| class vit(nn.Module): | |
| def __init__(self,height=224,width=224,n_channels=3,patch_size=16,batch_size=2,dim=512,n_head=2,feed_forward=1024,num_blocks=4,num_classes=1): | |
| super().__init__() | |
| self.embedding = patch_embedding(height,width,n_channels,patch_size,batch_size,dim) | |
| self.n_patchs = height*width//(patch_size**2) | |
| # Create a diagonal attention mask | |
| self.diag_attn_mask = torch.eye(self.n_patchs, dtype=torch.bool) | |
| self.transformer_encoder = Transformer(dim,num_blocks,n_head,feed_forward) | |
| self.mlp_block = nn.Sequential( | |
| nn.LayerNorm(dim), | |
| nn.Linear(dim, num_classes), | |
| ) | |
| def forward(self, inputs): | |
| #x bs,h,w,c | |
| device_ = inputs.device | |
| x = self.embedding(inputs) | |
| x = self.transformer_encoder(x,mask=self.diag_attn_mask.to(device_)) | |
| outputs = self.mlp_block(x.mean(dim=1)) | |
| return outputs | |
| class VITModelForImageClassification(PreTrainedModel): | |
| config_class = VITConfig | |
| def __init__(self, config : VITConfig): | |
| super().__init__(config) | |
| self.model = vit(config.height,config.width, | |
| config.n_channels,config.patch_size, | |
| config.batch_size,config.dim, | |
| config.n_head,config.feed_forward, | |
| config.num_blocks,config.num_classes) | |
| def forward(self, img,labels = None): | |
| logits = self.model(img) | |
| if labels is not None: | |
| loss_fnc = nn.CrossEntropyLoss() | |
| loss = loss_fnc(logits, labels) | |
| return {"loss": loss, "logits": logits} | |
| return {"logits": logits} | |