Skip to content

Commit

Permalink
fix: filters
Browse files Browse the repository at this point in the history
Signed-off-by: Kushal Batra <[email protected]>
Signed-off-by: Avik Basu <[email protected]>
  • Loading branch information
s0nicboOm authored and ab93 committed May 8, 2024
1 parent 87c16da commit 6f46250
Show file tree
Hide file tree
Showing 13 changed files with 187 additions and 85 deletions.
19 changes: 16 additions & 3 deletions numalogic/backtest/_prom.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ class OutDataFrames:
thresh_out: pd.DataFrame
postproc_out: pd.DataFrame
unified_out: pd.DataFrame
static_out: Optional[pd.DataFrame] = None
static_features: Optional[pd.DataFrame] = None
adjusted_unified: Optional[pd.DataFrame] = None


class PromBacktester:
Expand Down Expand Up @@ -288,14 +291,24 @@ def generate_scores(
[np.full((len(x_test) - len(ds), 1), fill_value=np.nan), unified_scores]
)

return self._construct_output(
out_dfs = self._construct_output(
df_test,
preproc_out=x_scaled,
nn_out=x_recon,
thresh_out=raw_scores,
postproc_out=feature_scores,
unified_out=unified_scores,
)
if self.nlconf.score.adjust:
static_scores = self.generate_static_scores(df_test)
out_dfs.static_out = static_scores["static_unified"]
out_dfs.static_features = static_scores["static_features"]

out_dfs.adjusted_unified = pd.concat(
[out_dfs.unified_out, out_dfs.static_out], axis=1
).max(axis=1)

return out_dfs

def generate_static_scores(self, df: pd.DataFrame) -> pd.DataFrame:
if not self.nlconf.score.adjust:
Expand All @@ -319,12 +332,12 @@ def generate_static_scores(self, df: pd.DataFrame) -> pd.DataFrame:
)
feature_scores = np.vstack(
[
np.full((self.seq_len - 1, len(metrics)), fill_value=np.nan),
np.full((len(x_test) - len(ds), len(metrics)), fill_value=np.nan),
feature_scores,
]
)
unified_scores = np.vstack(
[np.full((self.seq_len - 1, 1), fill_value=np.nan), unified_scores]
[np.full((len(x_test) - len(ds), 1), fill_value=np.nan), unified_scores]
)
dfs = {
"input": df,
Expand Down
22 changes: 6 additions & 16 deletions numalogic/models/autoencoder/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@

from typing import Any

import torch.nn.functional as F
from torch import Tensor, optim

from numalogic.base import TorchModel
from numalogic.tools.loss import get_loss_fn


class BaseAE(TorchModel):
Expand All @@ -41,19 +41,9 @@ def __init__(
super().__init__()
self.lr = lr
self.optim_algo = optim_algo
self.criterion = self.init_criterion(loss_fn)
self.criterion = get_loss_fn(loss_fn)
self.weight_decay = weight_decay

@staticmethod
def init_criterion(loss_fn: str):
if loss_fn == "huber":
return F.huber_loss
if loss_fn == "l1":
return F.l1_loss
if loss_fn == "mse":
return F.mse_loss
raise NotImplementedError(f"Unsupported loss function provided: {loss_fn}")

def init_optimizer(self, optim_algo: str):
if optim_algo == "adam":
return optim.Adam(self.parameters(), lr=self.lr, weight_decay=self.weight_decay)
Expand All @@ -67,9 +57,9 @@ def configure_shape(self, x: Tensor) -> Tensor:
"""Method to configure the batch shape for each type of model architecture."""
return x

def _get_reconstruction_loss(self, batch: Tensor) -> Tensor:
def get_reconstruction_loss(self, batch: Tensor, reduction="mean") -> Tensor:
_, recon = self.forward(batch)
return self.criterion(batch, recon)
return self.criterion(batch, recon, reduction=reduction)

def reconstruction(self, batch: Tensor) -> Tensor:
_, recon = self.forward(batch)
Expand All @@ -80,11 +70,11 @@ def configure_optimizers(self) -> dict[str, Any]:
return {"optimizer": optimizer}

def training_step(self, batch: Tensor, batch_idx: int) -> Tensor:
recon_loss = self._get_reconstruction_loss(batch)
recon_loss = self.get_reconstruction_loss(batch)
self.log("train_loss", recon_loss, on_epoch=True, on_step=False)
return recon_loss

def validation_step(self, batch: Tensor, batch_idx: int) -> Tensor:
recon_loss = self._get_reconstruction_loss(batch)
recon_loss = self.get_reconstruction_loss(batch)
self.log("val_loss", recon_loss)
return recon_loss
9 changes: 3 additions & 6 deletions numalogic/models/autoencoder/variants/conv.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ class Conv1dAE(BaseAE):
dec_activation: The final activation for the decoder
Supported values include: ("sigmoid", "tanh", "relu")
If None then no output activation is added
**kwargs: BaseAE kwargs
Note: Length of list/tuple of enc_channels and enc_kernel_sizes must be equal
"""
Expand Down Expand Up @@ -284,10 +285,6 @@ def encode(self, batch: Tensor) -> Tensor:
batch = self.configure_shape(batch)
return self.encoder(batch)

def _get_reconstruction_loss(self, batch: Tensor) -> Tensor:
_, recon = self.forward(batch)
return self.criterion(batch, recon)

def predict_step(self, batch: Tensor, batch_idx: int, dataloader_idx: int = 0) -> Tensor:
"""Returns reconstruction for streaming input."""
recon = self.reconstruction(batch)
Expand All @@ -308,7 +305,7 @@ class SparseConv1dAE(Conv1dAE):
----
beta: Penalty factor (Defaults to 1e-3)
rho: Sparsity parameter value (Defaults to 0.05)
**kwargs: VanillaAE kwargs
**kwargs: Conv1dAE kwargs
"""

def __init__(self, beta: float = 1e-3, rho: float = 0.05, *args, **kwargs):
Expand All @@ -335,7 +332,7 @@ def kl_divergence(self, activations: Tensor) -> Tensor:
)
return torch.sum(torch.clamp(kl_loss, max=1.0))

def _get_reconstruction_loss(self, batch) -> Tensor:
def get_reconstruction_loss(self, batch: Tensor, reduction="mean") -> Tensor:
latent, recon = self.forward(batch)
loss = self.criterion(batch, recon)
penalty = self.kl_divergence(latent)
Expand Down
8 changes: 4 additions & 4 deletions numalogic/models/autoencoder/variants/lstm.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def __init__(
embedding_dim: int,
encoder_layers: int = 1,
decoder_layers: int = 1,
**kwargs
**kwargs,
):
super().__init__(**kwargs)

Expand Down Expand Up @@ -146,7 +146,7 @@ def forward(self, x: Tensor) -> tuple[Tensor, Tensor]:
decoded = self.decoder(encoded)
return encoded, decoded

def predict_step(self, batch: Tensor, batch_idx: int, dataloader_idx: int = 0):
def predict_step(self, batch: Tensor, batch_idx: int, dataloader_idx: int = 0) -> Tensor:
"""Returns reconstruction for streaming input."""
recon = self.reconstruction(batch)
return self.criterion(batch, recon, reduction="none")
Expand All @@ -166,7 +166,7 @@ class SparseLSTMAE(LSTMAE):
----
beta: regularization parameter (Defaults to 1e-3)
rho: sparsity parameter value (Defaults to 0.05)
**kwargs: VanillaAE kwargs
**kwargs: LSTMAE kwargs
"""

def __init__(self, beta=1e-3, rho=0.05, *args, **kwargs):
Expand All @@ -192,7 +192,7 @@ def kl_divergence(self, activations: Tensor) -> Tensor:
_dim = 0 if rho_hat.dim() == 1 else 1
return kl_loss(torch.log_softmax(rho_hat, dim=_dim), torch.softmax(rho, dim=_dim))

def _get_reconstruction_loss(self, batch):
def get_reconstruction_loss(self, batch: Tensor, reduction="mean") -> Tensor:
latent, recon = self.forward(batch)
loss = self.criterion(batch, recon)
penalty = self.kl_divergence(latent)
Expand Down
6 changes: 3 additions & 3 deletions numalogic/models/autoencoder/variants/transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ def __init__(
dim_feedforward: int = 2048,
dropout: float = 0.1,
activation: nn.Module = nn.ReLU(),
**kwargs
**kwargs,
):
super().__init__(**kwargs)
self.n_features = n_features
Expand Down Expand Up @@ -348,7 +348,7 @@ def forward(self, batch: Tensor) -> tuple[Tensor, Tensor]:
decoded = self.decoder(batch, encoded)
return encoded, decoded

def _get_reconstruction_loss(self, batch):
def get_reconstruction_loss(self, batch):
_, recon = self.forward(batch)
x = batch.view(-1, self.n_features, self.seq_len)
return self.criterion(x, recon)
Expand Down Expand Up @@ -400,7 +400,7 @@ def kl_divergence(self, activations: Tensor) -> Tensor:
_dim = 0 if rho_hat.dim() == 1 else 1
return kl_loss(torch.log_softmax(rho_hat, dim=_dim), torch.softmax(rho, dim=_dim))

def _get_reconstruction_loss(self, batch):
def get_reconstruction_loss(self, batch):
latent, recon = self.forward(batch)
x = batch.view(-1, self.n_features, self.seq_len)
loss = self.criterion(x, recon)
Expand Down
Loading

0 comments on commit 6f46250

Please sign in to comment.