Spaces:
Sleeping
Sleeping
Download models/decoder.py from quoctk31/mathsnap-ai: direct link, hf CLI and curl.
- Browser
- Download file 3.82 kB
-
https://huggingface.co/spaces/quoctk31/mathsnap-ai/resolve/main/models/decoder.py
- Command line
-
hf download hf://spaces/quoctk31/mathsnap-ai/models/decoder.py
-
curl -L -o decoder.py https://huggingface.co/spaces/quoctk31/mathsnap-ai/resolve/main/models/decoder.py
3.82 kB
| """ | |
| CoMER decoder: Transformer with ARM (Attention Refinement Module). | |
| Based on: https://github.com/Green-Wood/CoMER | |
| Stripped from ICAL: removed SCCM, FusionModule, implicit/fusion heads. | |
| """ | |
| from typing import List | |
| import torch | |
| import torch.nn as nn | |
| from einops import rearrange | |
| from torch import FloatTensor, LongTensor | |
| from .pos_enc import WordPosEnc | |
| from .transformer.arm import AttentionRefinementModule | |
| from .transformer.transformer_decoder import ( | |
| TransformerDecoder, | |
| TransformerDecoderLayer, | |
| ) | |
| def _build_transformer_decoder( | |
| d_model: int, | |
| nhead: int, | |
| num_decoder_layers: int, | |
| dim_feedforward: int, | |
| dropout: float, | |
| dc: int, | |
| cross_coverage: bool, | |
| self_coverage: bool, | |
| ) -> TransformerDecoder: | |
| decoder_layer = TransformerDecoderLayer( | |
| d_model=d_model, | |
| nhead=nhead, | |
| dim_feedforward=dim_feedforward, | |
| dropout=dropout, | |
| ) | |
| if cross_coverage or self_coverage: | |
| arm = AttentionRefinementModule( | |
| nhead, dc, cross_coverage, self_coverage) | |
| else: | |
| arm = None | |
| decoder = TransformerDecoder(decoder_layer, num_decoder_layers, arm) | |
| return decoder | |
| class Decoder(nn.Module): | |
| def __init__( | |
| self, | |
| d_model: int, | |
| nhead: int, | |
| num_decoder_layers: int, | |
| dim_feedforward: int, | |
| dropout: float, | |
| dc: int, | |
| cross_coverage: bool, | |
| self_coverage: bool, | |
| vocab_size: int, | |
| pad_idx: int = 0, | |
| ): | |
| super().__init__() | |
| self.pad_idx = pad_idx | |
| self.word_embed = nn.Sequential( | |
| nn.Embedding(vocab_size, d_model), nn.LayerNorm(d_model) | |
| ) | |
| self.pos_enc = WordPosEnc(d_model=d_model) | |
| self.norm = nn.LayerNorm(d_model) | |
| self.model = _build_transformer_decoder( | |
| d_model=d_model, | |
| nhead=nhead, | |
| num_decoder_layers=num_decoder_layers, | |
| dim_feedforward=dim_feedforward, | |
| dropout=dropout, | |
| dc=dc, | |
| cross_coverage=cross_coverage, | |
| self_coverage=self_coverage, | |
| ) | |
| # Single projection head (CoMER) | |
| self.proj = nn.Linear(d_model, vocab_size) | |
| def _build_attention_mask(self, length, device): | |
| mask = torch.full( | |
| (length, length), fill_value=1, dtype=torch.bool, device=device | |
| ) | |
| mask.triu_(1) | |
| return mask | |
| def forward( | |
| self, src: FloatTensor, src_mask: LongTensor, tgt: LongTensor | |
| ) -> FloatTensor: | |
| """ | |
| Parameters | |
| ---------- | |
| src : FloatTensor [b, h, w, d] | |
| src_mask: LongTensor [b, h, w] | |
| tgt : LongTensor [b, l] | |
| Returns | |
| ------- | |
| FloatTensor [b, l, vocab_size] | |
| """ | |
| _, l = tgt.size() | |
| tgt_mask = self._build_attention_mask(l, tgt.device) | |
| tgt_pad_mask = tgt == self.pad_idx | |
| tgt = self.word_embed(tgt) # [b, l, d] | |
| tgt = self.pos_enc(tgt) # [b, l, d] | |
| tgt = self.norm(tgt) | |
| h = src.shape[1] | |
| src = rearrange(src, "b h w d -> (h w) b d") | |
| src_mask = rearrange(src_mask, "b h w -> b (h w)") | |
| tgt = rearrange(tgt, "b l d -> l b d") | |
| out = self.model( | |
| tgt=tgt, | |
| memory=src, | |
| height=h, | |
| tgt_mask=tgt_mask, | |
| tgt_key_padding_mask=tgt_pad_mask, | |
| memory_key_padding_mask=src_mask, | |
| ) | |
| out = rearrange(out, "l b d -> b l d") | |
| out = self.proj(out) | |
| return out | |
| def transform( | |
| self, src: List[FloatTensor], src_mask: List[LongTensor], input_ids: LongTensor | |
| ) -> FloatTensor: | |
| """For beam search: run forward and return logits.""" | |
| assert len(src) == 1 and len(src_mask) == 1 | |
| return self(src[0], src_mask[0], input_ids) | |