Spaces:
Build error
Build error
Download transformer/model.py from Manu8/Image_captioning: direct link, hf CLI and curl.
- Browser
- Download file 5.19 kB
-
https://huggingface.co/spaces/Manu8/Image_captioning/resolve/main/transformer/model.py
- Command line
-
hf download hf://spaces/Manu8/Image_captioning/transformer/model.py
-
curl -L -o model.py https://huggingface.co/spaces/Manu8/Image_captioning/resolve/main/transformer/model.py
5.19 kB
| from .attention import * | |
| from .embeddings import * | |
| def create_mask_decoder(target,padding_idx=0): | |
| seq_len = target.size(1) | |
| pad_mask = (target != padding_idx).unsqueeze(1).unsqueeze(2) | |
| seq_mask = torch.tril(torch.ones(seq_len, seq_len)).to(target.device) | |
| trg_mask = pad_mask * seq_mask | |
| return trg_mask | |
| 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.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 Encoder(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([ | |
| MultiHeadSelfAttention(embed_dim,heads), | |
| nn.LayerNorm(embed_dim), | |
| feedforward(embed_dim,ff_hidden_dim, dropout_rate), | |
| nn.LayerNorm(embed_dim), | |
| ])) | |
| def forward(self, source,target=None,mask=None): | |
| x = source.clone() | |
| for attn,norm, ff,norm2 in self.layers: | |
| x = attn(Q=x,K=x,V=x,attn_mask = mask) + x | |
| x = norm(x) | |
| x = ff(x) + x | |
| x = norm(x) | |
| return x | |
| class Decoder(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([ | |
| MultiHeadSelfAttention(embed_dim,heads), # masked self attention | |
| nn.LayerNorm(embed_dim), | |
| MultiHeadSelfAttention(embed_dim,heads), # cross atention | |
| nn.LayerNorm(embed_dim), | |
| feedforward(embed_dim,ff_hidden_dim, dropout_rate), # feed forward | |
| nn.LayerNorm(embed_dim) | |
| ])) | |
| def forward(self,encoder_out,decoder_in,mask=None): | |
| x = decoder_in.clone() | |
| for self_attn,norm1,cross_attn,norm2, ff,norm3 in self.layers: | |
| x = self_attn(Q=x,K=x,V=x,attn_mask = mask) + x | |
| x = norm1(x) | |
| x = cross_attn(Q=x,V=encoder_out,K=encoder_out) + x | |
| x = norm2(x) | |
| x = ff(x) + x | |
| x = norm3(x) | |
| return x | |
| class Transformer(nn.Module): | |
| def __init__(self,height=224, | |
| width=224, | |
| n_channels=3, | |
| patch_size=16, | |
| dim=512, | |
| encoder_head=2, | |
| encoder_feed_forward=1024, | |
| encoder_depth=2, | |
| decoder_head=2, | |
| decoder_feed_forward=1024, | |
| decoder_depth=1, | |
| targ_len = 10, | |
| vocab_size = 100, | |
| padding_idx = 0): | |
| super().__init__() | |
| self.image_embedding = patch_embedding(height,width,n_channels,patch_size,dim) | |
| self.decoder_embedding = nn.Embedding(vocab_size,dim, padding_idx=padding_idx) | |
| self.decoder_positional = PositionalEncoding(dim, targ_len) | |
| 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.encoder = Encoder(dim,encoder_depth, encoder_head,encoder_feed_forward) | |
| self.decoder = Decoder(dim,decoder_depth, decoder_head,decoder_feed_forward) | |
| self.padding_idx = padding_idx | |
| self.fc = nn.Linear(dim,vocab_size) | |
| def encode(self,image): | |
| device_ = image.device | |
| x = self.image_embedding(image) | |
| out = self.encoder(x,x,mask=self.diag_attn_mask.to(device_)) | |
| return out | |
| def decode(self,encoder_out,text): | |
| device_ = encoder_out.device | |
| decoder_mask = create_mask_decoder(text,padding_idx=self.padding_idx) | |
| y = self.decoder_positional(self.decoder_embedding(text)) | |
| out = self.decoder(encoder_out,y,mask=decoder_mask.to(device_)) | |
| return self.fc(out) | |
| def forward(self, image, text): | |
| encoder_out = self.encode(image) | |
| outputs = self.decode(encoder_out,text) | |
| return outputs | |
| def greedy_decoding(model, image, max_len, start_idx,end_idx): | |
| model.eval() | |
| decoder_input = torch.ones(1, 1, dtype=torch.long) * start_idx | |
| decoded_outputs = decoder_input | |
| decoded_outputs = decoded_outputs.to(image.device) | |
| encoder_out = model.encode(image) | |
| for i in range(max_len): | |
| decoder_output = model.decode(encoder_out,decoded_outputs) # Decode next token | |
| next_word = decoder_output[:, -1].argmax(dim=-1).unsqueeze(-1) # Get most probable word index | |
| if next_word==end_idx: | |
| break | |
| decoded_outputs = torch.cat([decoded_outputs, next_word], dim=-1) # Append next word to output sequence | |
| return decoded_outputs[:, 1:] |