Download model.py from Nefflymicn/Amazon-Sentiment-LiveDemo: direct link, hf CLI and curl.
- Browser
- Download file 3.12 kB
-
https://huggingface.co/spaces/Nefflymicn/Amazon-Sentiment-LiveDemo/resolve/main/model.py
- Command line
-
hf download hf://spaces/Nefflymicn/Amazon-Sentiment-LiveDemo/model.py
-
curl -L -o model.py https://huggingface.co/spaces/Nefflymicn/Amazon-Sentiment-LiveDemo/resolve/main/model.py
3.12 kB
| import math | |
| import torch | |
| import torch.nn as nn | |
| class PositionalEncoding(nn.Module): | |
| def __init__(self, d_model, max_len=5000): | |
| super(PositionalEncoding, self).__init__() | |
| # create a matrix of [max_len, d_model] filled with zeros | |
| pe = torch.zeros(max_len, d_model) | |
| # Create a column vector of positions [0, 1, 2, ..., max_len -1] | |
| position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1) | |
| # Calculate the "division term" for the cos/sin math | |
| div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model)) | |
| # Fill even indices (0, 2, 4, ...) with Sine | |
| pe[:, 0::2] = torch.sin(position * div_term) | |
| # Fill odd indices (1, 3, 5, ...) with Cosine | |
| pe[:, 1::2] = torch.cos(position * div_term) | |
| # Add a batch dimension [1, max_len, d_model] | |
| pe = pe.unsqueeze(0) | |
| # register buffer ensures this is saved with the model but not trained | |
| self.register_buffer('pe', pe) | |
| def forward(self, x): | |
| # x is word embeddings [Batch, Seq_len, d-model] | |
| # We simply add the positional vectors to the word vectors | |
| x = x + self.pe[:, :x.size(1)] | |
| return x | |
| class TransformerBlock(nn.Module): | |
| def __init__(self, embed_dim, num_heads, ff_dim, dropout=0.1): | |
| super(TransformerBlock, self).__init__() | |
| # Multihead Attention: How many different "perspectives" the model has (num_heads) | |
| self.attention = nn.MultiheadAttention(embed_dim, num_heads, batch_first=True) | |
| # Layer Normalization | |
| self.norm1 = nn.LayerNorm(embed_dim) | |
| self.norm2 = nn.LayerNorm(embed_dim) | |
| # Feed Forward Network | |
| self.ff = nn.Sequential( | |
| nn.Linear(embed_dim, ff_dim), | |
| nn.ReLU(), | |
| nn.Linear(ff_dim, embed_dim) | |
| ) | |
| self.dropout = nn.Dropout(dropout) | |
| def forward(self, x): | |
| # x shape: [batch, seq_len, embed_dim] | |
| # Attention (Residual + Norm) | |
| attn_output, _ = self.attention(x, x, x) | |
| x = self.norm1(x + self.dropout(attn_output)) | |
| # Feed Forward (Residual Connection +_Norm) | |
| ff_output = self.ff(x) | |
| x = self.norm2(x + self.dropout(ff_output)) | |
| return x | |
| class TransformerSentimentModel(nn.Module): | |
| def __init__(self, vocab_size, embed_dim, num_heads, ff_dim, num_layers, output_dim, max_len=300): | |
| super(TransformerSentimentModel, self).__init__() | |
| self.embedding = nn.Embedding(vocab_size, embed_dim) | |
| self.pos_encoding = PositionalEncoding(embed_dim, max_len) | |
| self.blocks = nn.ModuleList([ | |
| TransformerBlock(embed_dim, num_heads, ff_dim) for _ in range(num_layers) | |
| ]) | |
| self.dropout = nn.Dropout(0.5) | |
| self.fc = nn.Linear(embed_dim, output_dim) | |
| def forward(self, input_ids): | |
| # x: [batch, seq_len] | |
| x = self.embedding(input_ids) # [batch, seq_len, embed_dim] | |
| x = self.pos_encoding(x) | |
| for block in self.blocks: | |
| x = block(x) | |
| x = x[:, 0, :] | |
| return self.fc(self.dropout(x)) |