|
|
| import torch |
| import torch.nn as nn |
| from transformers import PretrainedConfig |
|
|
|
|
| class CustomDecoderConfig(PretrainedConfig): |
| model_type = "custom-transformer-decoder" |
|
|
| def __init__( |
| self, |
| vocab_size=30522, |
| max_position_embeddings=128, |
| hidden_size=256, |
| num_attention_heads=8, |
| intermediate_size=1024, |
| num_hidden_layers=4, |
| hidden_dropout_prob=0.1, |
| attention_probs_dropout_prob=0.1, |
| **kwargs |
| ): |
| super().__init__(**kwargs) |
|
|
| |
| self.vocab_size = vocab_size |
|
|
| |
| self.max_position_embeddings = max_position_embeddings |
|
|
| |
| self.hidden_size = hidden_size |
|
|
| |
| self.num_attention_heads = num_attention_heads |
|
|
| |
| self.intermediate_size = intermediate_size |
|
|
| |
| self.num_hidden_layers = num_hidden_layers |
|
|
| |
| self.hidden_dropout_prob = hidden_dropout_prob |
|
|
| |
| self.attention_probs_dropout_prob = attention_probs_dropout_prob |
|
|
|
|
| class PositionWiseFeedForward(nn.Module): |
| def __init__(self, hidden_size, intermediate_size, dropout_prob): |
| super().__init__() |
|
|
| |
| self.linear_1 = nn.Linear(hidden_size, intermediate_size) |
|
|
| |
| self.activation = nn.GELU() |
|
|
| |
| self.linear_2 = nn.Linear(intermediate_size, hidden_size) |
|
|
| |
| self.dropout = nn.Dropout(dropout_prob) |
|
|
| def forward(self, x): |
| |
| x = self.linear_1(x) |
| x = self.activation(x) |
| x = self.dropout(x) |
| x = self.linear_2(x) |
| return x |
|
|
|
|
| class DecoderBlock(nn.Module): |
| def __init__(self, config): |
| super().__init__() |
|
|
| |
| self.masked_self_attention = nn.MultiheadAttention( |
| embed_dim=config.hidden_size, |
| num_heads=config.num_attention_heads, |
| dropout=config.attention_probs_dropout_prob, |
| batch_first=True |
| ) |
|
|
| |
| self.norm_1 = nn.LayerNorm(config.hidden_size) |
|
|
| |
| self.cross_attention = nn.MultiheadAttention( |
| embed_dim=config.hidden_size, |
| num_heads=config.num_attention_heads, |
| dropout=config.attention_probs_dropout_prob, |
| batch_first=True |
| ) |
|
|
| |
| self.norm_2 = nn.LayerNorm(config.hidden_size) |
|
|
| |
| self.feed_forward = PositionWiseFeedForward( |
| hidden_size=config.hidden_size, |
| intermediate_size=config.intermediate_size, |
| dropout_prob=config.hidden_dropout_prob |
| ) |
|
|
| |
| self.norm_3 = nn.LayerNorm(config.hidden_size) |
|
|
| |
| self.dropout = nn.Dropout(config.hidden_dropout_prob) |
|
|
| def forward(self, x, encoder_output=None, self_attention_mask=None, cross_attention_mask=None): |
| |
| residual = x |
|
|
| |
| self_attention_output, _ = self.masked_self_attention( |
| query=x, |
| key=x, |
| value=x, |
| attn_mask=self_attention_mask |
| ) |
|
|
| |
| x = self.norm_1(residual + self.dropout(self_attention_output)) |
|
|
| if encoder_output is not None: |
| |
| residual = x |
|
|
| |
| cross_attention_output, _ = self.cross_attention( |
| query=x, |
| key=encoder_output, |
| value=encoder_output, |
| key_padding_mask=cross_attention_mask |
| ) |
|
|
| |
| x = self.norm_2(residual + self.dropout(cross_attention_output)) |
|
|
| |
| residual = x |
|
|
| |
| ff_output = self.feed_forward(x) |
|
|
| |
| x = self.norm_3(residual + self.dropout(ff_output)) |
|
|
| return x |
|
|
|
|
| class TransformerDecoder(nn.Module): |
| def __init__(self, config): |
| super().__init__() |
|
|
| |
| self.token_embedding = nn.Embedding( |
| config.vocab_size, |
| config.hidden_size |
| ) |
|
|
| |
| self.position_embedding = nn.Embedding( |
| config.max_position_embeddings, |
| config.hidden_size |
| ) |
|
|
| |
| self.layers = nn.ModuleList([ |
| DecoderBlock(config) for _ in range(config.num_hidden_layers) |
| ]) |
|
|
| |
| self.dropout = nn.Dropout(config.hidden_dropout_prob) |
|
|
| |
| self.final_norm = nn.LayerNorm(config.hidden_size) |
|
|
| |
| self.lm_head = nn.Linear(config.hidden_size, config.vocab_size) |
|
|
| self.config = config |
|
|
| def make_causal_mask(self, seq_length, device): |
| |
| mask = torch.triu( |
| torch.ones(seq_length, seq_length, device=device), |
| diagonal=1 |
| ).bool() |
| return mask |
|
|
| def forward(self, input_ids, encoder_output=None, cross_attention_mask=None): |
| batch_size, seq_length = input_ids.size() |
|
|
| |
| position_ids = torch.arange( |
| seq_length, |
| dtype=torch.long, |
| device=input_ids.device |
| ).unsqueeze(0).expand(batch_size, seq_length) |
|
|
| |
| x = self.token_embedding(input_ids) + self.position_embedding(position_ids) |
| x = self.dropout(x) |
|
|
| |
| self_attention_mask = self.make_causal_mask(seq_length, input_ids.device) |
|
|
| |
| for layer in self.layers: |
| x = layer( |
| x, |
| encoder_output=encoder_output, |
| self_attention_mask=self_attention_mask, |
| cross_attention_mask=cross_attention_mask |
| ) |
|
|
| x = self.final_norm(x) |
|
|
| |
| logits = self.lm_head(x) |
|
|
| return logits |
|
|
|
|
| if __name__ == "__main__": |
| config = CustomDecoderConfig() |
| model = TransformerDecoder(config) |
|
|
| input_ids = torch.randint(0, config.vocab_size, (2, 10)) |
| encoder_output = torch.randn(2, 10, config.hidden_size) |
|
|
| logits = model(input_ids, encoder_output=encoder_output) |
|
|
| print("Input shape:", input_ids.shape) |
| print("Logits shape:", logits.shape) |
|
|