myanmar-ghost / models /base_model.py
amkyawdev's picture
Add source code
cfb5e7f verified
Raw
History Blame Contribute Delete
3.27 kB
"""Base model class for Myanmar Ghost project."""
import logging
from abc import ABC, abstractmethod
from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple
import torch
import torch.nn as nn
logger = logging.getLogger(__name__)
class BaseModel(ABC, nn.Module):
"""Abstract base class for all models."""
def __init__(self, config: Optional[Dict] = None):
super().__init__()
self.config = config or {}
self.device = torch.device(
"cuda" if torch.cuda.is_available() else "cpu"
)
@abstractmethod
def forward(self, *args, **kwargs) -> torch.Tensor:
"""Forward pass."""
pass
@abstractmethod
def predict(self, *args, **kwargs) -> Dict[str, Any]:
"""Make predictions."""
pass
def save(self, path: str) -> None:
"""Save model checkpoint."""
Path(path).parent.mkdir(parents=True, exist_ok=True)
torch.save({
"model_state_dict": self.state_dict(),
"config": self.config,
}, path)
logger.info(f"Model saved to {path}")
def load(self, path: str) -> None:
"""Load model checkpoint."""
checkpoint = torch.load(path, map_location=self.device)
self.load_state_dict(checkpoint["model_state_dict"])
if "config" in checkpoint:
self.config = checkpoint["config"]
logger.info(f"Model loaded from {path}")
def get_num_parameters(self) -> int:
"""Get total number of parameters."""
return sum(p.numel() for p in self.parameters())
def get_num_trainable_parameters(self) -> int:
"""Get number of trainable parameters."""
return sum(p.numel() for p in self.parameters() if p.requires_grad)
class SentimentClassifier(nn.Module):
"""Base sentiment classifier."""
def __init__(
self,
input_dim: int,
hidden_dim: int,
num_classes: int = 4,
dropout: float = 0.1,
):
super().__init__()
self.fc1 = nn.Linear(input_dim, hidden_dim)
self.dropout = nn.Dropout(dropout)
self.fc2 = nn.Linear(hidden_dim, hidden_dim // 2)
self.fc3 = nn.Linear(hidden_dim // 2, num_classes)
self.relu = nn.ReLU()
def forward(self, x: torch.Tensor) -> torch.Tensor:
x = self.relu(self.fc1(x))
x = self.dropout(x)
x = self.relu(self.fc2(x))
x = self.dropout(x)
x = self.fc3(x)
return x
def create_model(
model_type: str = "transformer",
**kwargs,
) -> BaseModel:
"""Factory function to create models."""
from .transformer_model import TransformerSentimentModel
from .multimodal_model import MultiModalSentimentModel
if model_type == "transformer":
return TransformerSentimentModel(**kwargs)
elif model_type == "multimodal":
return MultiModalSentimentModel(**kwargs)
elif model_type == "base":
return SentimentClassifier(**kwargs)
else:
raise ValueError(f"Unknown model type: {model_type}")
if __name__ == "__main__":
model = SentimentClassifier(input_dim=768, hidden_dim=256, num_classes=4)
print(f"Model parameters: {model.get_num_parameters():,}")