| import torch |
| import torch.nn as nn |
| import numpy as np |
| from pathlib import Path |
| from typing import Optional |
|
|
|
|
| class BetaRegressor(nn.Module): |
| def __init__(self, input_dim: int = 9, output_dim: int = 10, hidden_dims: list = [64, 32]): |
| super(BetaRegressor, self).__init__() |
| |
| layers = [] |
| prev_dim = input_dim |
| |
| for hidden_dim in hidden_dims: |
| layers.append(nn.Linear(prev_dim, hidden_dim)) |
| layers.append(nn.ReLU()) |
| layers.append(nn.Dropout(0.1)) |
| prev_dim = hidden_dim |
| |
| layers.append(nn.Linear(prev_dim, output_dim)) |
| layers.append(nn.Tanh()) |
| |
| self.network = nn.Sequential(*layers) |
| self._initialize_weights() |
| |
| def _initialize_weights(self): |
| for m in self.modules(): |
| if isinstance(m, nn.Linear): |
| nn.init.xavier_uniform_(m.weight, gain=0.1) |
| nn.init.zeros_(m.bias) |
| |
| def forward(self, x: torch.Tensor) -> torch.Tensor: |
| return self.network(x) |
|
|
|
|
| class MeasurementToBetaPredictor: |
| def __init__(self, model_path: Optional[str] = None, device: str = "cpu"): |
| self.device = torch.device(device) |
| self.model = BetaRegressor().to(self.device) |
| self.model.eval() |
| |
| if model_path and Path(model_path).exists(): |
| self.load_model(model_path) |
| else: |
| print("Warning: Using untrained model. Results may not be optimal.") |
| print("Consider training the model or loading pretrained weights.") |
| |
| def load_model(self, model_path: str): |
| checkpoint = torch.load(model_path, map_location=self.device) |
| if isinstance(checkpoint, dict) and 'model_state_dict' in checkpoint: |
| self.model.load_state_dict(checkpoint['model_state_dict']) |
| else: |
| self.model.load_state_dict(checkpoint) |
| print(f"Loaded model from {model_path}") |
| |
| def predict(self, normalized_measurements: np.ndarray) -> np.ndarray: |
| with torch.no_grad(): |
| measurements_tensor = torch.FloatTensor(normalized_measurements).unsqueeze(0).to(self.device) |
| betas_tensor = self.model(measurements_tensor) |
| betas = betas_tensor.squeeze(0).cpu().numpy() |
| betas = betas * 2.0 |
| |
| return betas |
|
|
|
|
| _predictor_instance = None |
|
|
|
|
| def get_predictor(model_path: Optional[str] = None, device: str = "cpu") -> MeasurementToBetaPredictor: |
| global _predictor_instance |
| if _predictor_instance is None: |
| _predictor_instance = MeasurementToBetaPredictor(model_path=model_path, device=device) |
| return _predictor_instance |
|
|
|
|
| def predict_betas(normalized_measurements: np.ndarray, model_path: Optional[str] = None) -> np.ndarray: |
| predictor = get_predictor(model_path=model_path) |
| return predictor.predict(normalized_measurements) |
|
|
|
|