tiny-transformers / src /task /model.py
zeguru's picture
Upload folder using huggingface_hub
1717c0c verified
Raw History Blame Contribute Delete
4.96 kB
"""Single Head transformer"""
import torch
import torch.nn as nn
from src.transformer.transformer import Transformer
from src.transformer.input_representation import InputRepresentation
class TinyTransformerLM(nn.Module):
def __init__(
self,
config,
vocab_size,
):
super().__init__()
print("Initializing TinyTransformerLM")
self.input_representation = InputRepresentation(
vocab_size=vocab_size,
context_length=config.context_length,
d_model=config.d_model,
)
self.transformer = Transformer(
d_model=config.d_model,
d_ff=config.d_ff,
context_length=config.context_length,
num_layers=config.num_layers,
number_of_heads=config.number_of_heads,
dropout=config.dropout,
#padding mask here
)
self.head = nn.Linear(
config.d_model,
vocab_size,
)
def forward(
self,
tokens: torch.Tensor,
) -> torch.Tensor:
x = self.input_representation(tokens)
x = self.transformer(x)
logits = self.head(x)
return logits
class TinyClassifier(nn.Module):
def __init__(
self,
config,
vocab_size,
num_classes=4,
):
super().__init__()
print("Initializing TinyClassifier")
self.input_representation = InputRepresentation(
vocab_size=vocab_size,
context_length=config.context_length,
d_model=config.d_model,
)
self.transformer = Transformer(
d_model=config.d_model,
d_ff=config.d_ff,
context_length=config.context_length,
num_layers=config.num_layers,
number_of_heads=config.number_of_heads,
dropout=config.dropout,
)
self.head = nn.Linear(
config.d_model,
num_classes,
)
def forward(
self,
tokens: torch.Tensor,
padding_mask: torch.Tensor | None = None,
) -> torch.Tensor:
x = self.input_representation(tokens)
x = self.transformer(
x,
padding_mask=padding_mask,
)
if padding_mask is None:
x = x.mean(dim=1)
else:
mask = padding_mask.unsqueeze(-1)
x = x * mask
token_count = mask.sum(
dim=1
).clamp(min=1)
x = x.sum(dim=1) / token_count
logits = self.head(x)
return logits
class TinyAnsweringModel(nn.Module):
def __init__(
self,
config,
vocab_size,
):
super().__init__()
print("Initializing TinyAnsweringModel")
self.input_representation = InputRepresentation(
vocab_size=vocab_size,
context_length=config.context_length,
d_model=config.d_model
)
self.transformer = Transformer(
d_model=config.d_model,
d_ff=config.d_ff,
context_length=config.context_length, #max_length used for truncating and padding input
num_layers=config.num_layers,
number_of_heads=config.number_of_heads,
dropout=config.dropout,
)
#TWO output projections
#Start of the answer
self.start_head = nn.Linear(
config.d_model, #IN features
1, #OUT features
)
# Predict where the answer ends.
self.end_head = nn.Linear(
config.d_model,
1, #why 1 ? should it not be max_length (or max_length)
)
def forward(
self,
tokens: torch.Tensor,
padding_mask: torch.Tensor,
) -> tuple[torch.Tensor, torch.Tensor]:
x = self.input_representation(tokens)
x = self.transformer(
x,
padding_mask=padding_mask,
)
start_logits = self.start_head(x).squeeze(-1)
end_logits = self.end_head(x).squeeze(-1)
return start_logits, end_logits
# Load language modelfrom checkpoint
def load_model(
checkpoint_path,
config,
vocab_size,
type="GENERATOR"
):
if (type == "GENERATOR"):
model = TinyTransformerLM(
config=config,
vocab_size=vocab_size,
)
elif (type == "CLASSIFIER"):
model = TinyClassifier(
config=config,
vocab_size=vocab_size,
)
elif (type == "ANSWERING"):
model = TinyAnsweringModel(
config=config,
vocab_size=vocab_size,
)
else:
print("UNKNOWN MODEL")
checkpoint = torch.load(
checkpoint_path,
map_location="cpu",
)
model.load_state_dict(checkpoint)
model.eval()
return model