dsipts 1.1.13__py3-none-any.whl → 1.1.15__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of dsipts might be problematic. Click here for more details.

dsipts/__init__.py CHANGED
@@ -26,6 +26,9 @@ from .models.TTM import TTM
26
26
  from .models.Samformer import Samformer
27
27
  from .models.Duet import Duet
28
28
  from .models.Simple import Simple
29
+ from .models.TimesNet import TimesNet
30
+ from .models.TimeKAN import TimeKAN
31
+ from .version import __version__
29
32
  try:
30
33
  import lightning.pytorch as pl
31
34
  from .models.base_v2 import Base
@@ -44,5 +47,5 @@ __all__ = [
44
47
  "RNN", "LinearTS", "Persistent", "D3VAE", "DilatedConv", "TFT",
45
48
  "Informer", "VVA", "VQVAEA", "CrossFormer", "Autoformer", "PatchTST",
46
49
  "Diffusion", "DilatedConvED", "TIDE", "ITransformer", "TimeXER",
47
- "TTM", "Samformer", "Duet", "Base", "Simple"
50
+ "TTM", "Samformer", "Duet", "Base", "Simple","TimesNet","TimeKAN"
48
51
  ]
@@ -451,7 +451,8 @@ class TimeSeries():
451
451
 
452
452
  idx_target = []
453
453
  for c in self.target_variables:
454
- idx_target.append(self.past_variables.index(c))
454
+ if c in self.past_variables:
455
+ idx_target.append(self.past_variables.index(c))
455
456
 
456
457
  idx_target_future = []
457
458
 
@@ -670,7 +671,7 @@ class TimeSeries():
670
671
  if c!=self.group:
671
672
  self.scaler_cat[f'{c}_{group}'] = OrdinalEncoder(dtype=np.int32,handle_unknown= 'use_encoded_value',unknown_value=train[c].nunique())
672
673
  self.scaler_cat[f'{c}_{group}'].fit(tmp[c].values.reshape(-1,1))
673
-
674
+
674
675
  dl_train = self.create_data_loader(train,past_steps,future_steps,shift,keep_entire_seq_while_shifting,starting_point,skip_step)
675
676
  dl_validation = self.create_data_loader(validation,past_steps,future_steps,shift,keep_entire_seq_while_shifting,starting_point,skip_step)
676
677
  if test.shape[0]>0:
@@ -772,7 +773,24 @@ class TimeSeries():
772
773
  else:
773
774
  train_dl = DataLoader(train, batch_size = batch_size , shuffle=True,drop_last=True,num_workers=num_workers,persistent_workers=persistent_workers)
774
775
  valid_dl = DataLoader(validation, batch_size = batch_size , shuffle=False,drop_last=True,num_workers=num_workers,persistent_workers=persistent_workers)
775
-
776
+ debug_prediction = True
777
+
778
+ if debug_prediction:
779
+ dl = DataLoader(test, batch_size = batch_size , shuffle=False,drop_last=True,num_workers=num_workers,persistent_workers=persistent_workers)
780
+ res = []
781
+ real = []
782
+ for batch in dl:
783
+
784
+
785
+ res.append(self.model.inference(batch).cpu().detach().numpy())
786
+ real.append(batch['y'].cpu().detach().numpy())
787
+
788
+ res = np.vstack(res)
789
+ real = np.vstack(real)
790
+ with open('/home/agobbi/Projects/ExpTS/tmp_beginning.pkl','wb') as f:
791
+ import pickle
792
+ pickle.dump([res,real],f)
793
+
776
794
  checkpoint_callback = ModelCheckpoint(dirpath=dirpath,
777
795
  monitor='val_loss',
778
796
  save_last = True,
@@ -867,23 +885,24 @@ class TimeSeries():
867
885
 
868
886
 
869
887
 
870
-
888
+
871
889
  if auto_lr_find and (weight_exists is False):
872
- if OLD_PL:
873
- lr_tuner = trainer.tune(self.model,train_dataloaders=train_dl,val_dataloaders = valid_dl)
874
- files = os.listdir(dirpath)
875
- for f in files:
876
- if '.lr_find' in f:
877
- os.remove(os.path.join(dirpath,f))
878
- self.model.optim_config['lr'] = lr_tuner['lr_find'].suggestion()
879
- else:
880
- from lightning.pytorch.tuner import Tuner
881
- tuner = Tuner(trainer)
882
- lr_finder = tuner.lr_find(self.model,train_dataloaders=train_dl,val_dataloaders = valid_dl)
883
- self.model.optim_config['lr'] = lr_finder.suggestion() ## we are using it as optim key
890
+ try:
891
+ if OLD_PL:
892
+ lr_tuner = trainer.tune(self.model,train_dataloaders=train_dl,val_dataloaders = valid_dl)
893
+ files = os.listdir(dirpath)
894
+ for f in files:
895
+ if '.lr_find' in f:
896
+ os.remove(os.path.join(dirpath,f))
897
+ self.model.optim_config['lr'] = lr_tuner['lr_find'].suggestion()
898
+ else:
899
+ from lightning.pytorch.tuner import Tuner
900
+ tuner = Tuner(trainer)
901
+ lr_finder = tuner.lr_find(self.model,train_dataloaders=train_dl,val_dataloaders = valid_dl)
902
+ self.model.optim_config['lr'] = lr_finder.suggestion() ## we are using it as optim key
903
+ except Exception as e:
904
+ beauty_string(f'There is a problem with the finding LR routine {e}','section',self.verbose)
884
905
 
885
-
886
-
887
906
  if OLD_PL:
888
907
  if weight_exists:
889
908
  trainer.fit(self.model, train_dl,valid_dl,ckpt_path=os.path.join(dirpath,'last.ckpt'))
@@ -894,17 +913,36 @@ class TimeSeries():
894
913
  trainer.fit(self.model, train_dataloaders = train_dl,val_dataloaders = valid_dl,ckpt_path=os.path.join(dirpath,'last.ckpt'))
895
914
  else:
896
915
  trainer.fit(self.model, train_dataloaders = train_dl,val_dataloaders = valid_dl)
916
+
897
917
  self.checkpoint_file_best = checkpoint_callback.best_model_path
898
918
  self.checkpoint_file_last = checkpoint_callback.last_model_path
899
919
  if self.checkpoint_file_last=='':
900
920
  beauty_string('There is a bug on saving last model I will try to fix it','info',self.verbose)
901
- self.checkpoint_file_last = checkpoint_callback.best_model_path.replace('checkpoint','last')
921
+ self.checkpoint_file_last = os.path.join(dirpath, "last.ckpt")
922
+ trainer.save_checkpoint(os.path.join(dirpath, "last.ckpt"))
923
+ if self.checkpoint_file_best=='':
924
+ beauty_string('There is a bug on saving best model I will try to fix it','info',self.verbose)
925
+ self.checkpoint_file_best = os.path.join(dirpath, "checkpoint.ckpt")
926
+ trainer.save_checkpoint(os.path.join(dirpath, "checkpoint.ckpt"))
902
927
 
903
928
  self.dirpath = dirpath
904
929
 
905
930
  self.losses = mc.metrics
906
931
 
907
932
  files = os.listdir(dirpath)
933
+ if debug_prediction:
934
+ res = []
935
+ real = []
936
+ for batch in dl:
937
+ res.append(self.model.inference(batch).cpu().detach().numpy())
938
+ real.append(batch['y'].cpu().detach().numpy())
939
+
940
+ res = np.vstack(res)
941
+ real = np.vstack(real)
942
+ with open('/home/agobbi/Projects/ExpTS/tmp_after_training.pkl','wb') as f:
943
+ import pickle
944
+ pickle.dump([res,real],f)
945
+
908
946
  ##accrocchio per multi gpu
909
947
  for f in files:
910
948
  if '__losses__.csv' in f:
@@ -917,7 +955,6 @@ class TimeSeries():
917
955
  self.losses = pd.DataFrame()
918
956
 
919
957
  try:
920
-
921
958
  if OLD_PL:
922
959
  if isinstance(self.model, torch._dynamo.eval_frame.OptimizedModule):
923
960
  self.model = self.model._orig_mod
@@ -930,7 +967,21 @@ class TimeSeries():
930
967
  self.model = mm.__class__.load_from_checkpoint(self.checkpoint_file_last)
931
968
  else:
932
969
  self.model = self.model.__class__.load_from_checkpoint(self.checkpoint_file_last)
970
+ if debug_prediction:
971
+ res = []
972
+ real = []
973
+ for batch in dl:
974
+
933
975
 
976
+ res.append(self.model.inference(batch).cpu().detach().numpy())
977
+ real.append(batch['y'].cpu().detach().numpy())
978
+
979
+ res = np.vstack(res)
980
+ real = np.vstack(real)
981
+ with open('/home/agobbi/Projects/ExpTS/tmp_after_loading.pkl','wb') as f:
982
+ import pickle
983
+ pickle.dump([res,real],f)
984
+
934
985
  except Exception as _:
935
986
  beauty_string(f'There is a problem loading the weights on file MAYBE CHANGED HOW WEIGHTS ARE LOADED {self.checkpoint_file_last}','section',self.verbose)
936
987
 
@@ -1008,12 +1059,15 @@ class TimeSeries():
1008
1059
  beauty_string(f'Device used: {self.model.device}','info',self.verbose)
1009
1060
 
1010
1061
  for batch in dl:
1062
+
1063
+
1011
1064
  res.append(self.model.inference(batch).cpu().detach().numpy())
1012
1065
  real.append(batch['y'].cpu().detach().numpy())
1013
-
1066
+
1014
1067
  res = np.vstack(res)
1015
-
1016
1068
  real = np.vstack(real)
1069
+
1070
+
1017
1071
  time = dl.dataset.t
1018
1072
  groups = dl.dataset.groups
1019
1073
  #import pdb
@@ -1203,15 +1257,21 @@ class TimeSeries():
1203
1257
 
1204
1258
  try:
1205
1259
  tmp_path = os.path.join(directory,self.checkpoint_file_last.split('/')[-1])
1260
+ beauty_string(f"Loading {tmp_path}",'section',self.verbose)
1261
+
1206
1262
  except Exception as _:
1207
1263
  beauty_string('checkpoint_file_last not defined try to load best','section',self.verbose)
1208
1264
  tmp_path = os.path.join(directory,self.checkpoint_file_best.split('/')[-1])
1265
+ beauty_string(f"Loading {tmp_path}",'section',self.verbose)
1209
1266
  else:
1210
1267
  try:
1268
+
1211
1269
  tmp_path = os.path.join(directory,self.checkpoint_file_best.split('/')[-1])
1270
+ beauty_string(f"Loading {tmp_path}",'section',self.verbose)
1212
1271
  except Exception as _:
1213
1272
  beauty_string('checkpoint_file_best not defined try to load best','section',self.verbose)
1214
1273
  tmp_path = os.path.join(directory,self.checkpoint_file_last.split('/')[-1])
1274
+ beauty_string(f"Loading {tmp_path}",'section',self.verbose)
1215
1275
  try:
1216
1276
  #with torch.serialization.add_safe_globals([ListConfig]):
1217
1277
  if OLD_PL:
@@ -1219,5 +1279,6 @@ class TimeSeries():
1219
1279
  else:
1220
1280
  self.model = self.model.__class__.load_from_checkpoint(tmp_path,verbose=self.verbose,)
1221
1281
  self.model.to(torch.device("cuda:0" if torch.cuda.is_available() else "cpu"))
1282
+
1222
1283
  except Exception as e:
1223
1284
  beauty_string(f'There is a problem loading the weights on file {tmp_path} {e}','section',self.verbose)
@@ -30,6 +30,8 @@ class Persistent(Base):
30
30
  self.save_hyperparameters(logger=False)
31
31
  self.fake = nn.Linear(1,1)
32
32
  self.use_quantiles = False
33
+ def can_be_compiled(self):
34
+ return False
33
35
 
34
36
  def forward(self, batch):
35
37
 
dsipts/models/TTM.py CHANGED
@@ -39,6 +39,7 @@ class TTM(Base):
39
39
  fcm_prepend_past,
40
40
  enable_forecast_channel_mixing,
41
41
  force_return,
42
+ few_shot = True,
42
43
  **kwargs)->None:
43
44
 
44
45
  super().__init__(**kwargs)
@@ -86,7 +87,8 @@ class TTM(Base):
86
87
  )
87
88
  hidden_size = self.model.config.hidden_size
88
89
  self.model.prediction_head = torch.nn.Linear(hidden_size, self.out_channels*self.mul)
89
- self._freeze_backbone()
90
+ if few_shot:
91
+ self._freeze_backbone()
90
92
  self.zero_pad = (force_return=='zeropad')
91
93
  def _freeze_backbone(self):
92
94
  """
@@ -113,7 +115,7 @@ class TTM(Base):
113
115
 
114
116
  def can_be_compiled(self):
115
117
 
116
- return True#not self.zero_pad
118
+ return True#True#not self.zero_pad
117
119
 
118
120
  def forward(self, batch):
119
121
  x_enc = batch['x_num_past'].to(self.device)
@@ -172,6 +174,7 @@ class TTM(Base):
172
174
 
173
175
 
174
176
  BS = res.shape[0]
177
+
175
178
  return res.reshape(BS,self.future_steps,-1,self.mul)
176
179
 
177
180
 
@@ -0,0 +1,123 @@
1
+ ## Copyright https://github.com/huangst21/TimeKAN/blob/main/models/TimeKAN.py
2
+ ## Modified for notation alignmenet and batch structure
3
+ ## extended to what inside itransformer folder
4
+
5
+ import torch
6
+ import torch.nn as nn
7
+ import numpy as np
8
+ from .timekan.Layers import FrequencyDecomp,FrequencyMixing,series_decomp,Normalize
9
+ from ..data_structure.utils import beauty_string
10
+ from .utils import get_scope,get_activation,Embedding_cat_variables
11
+
12
+ try:
13
+ import lightning.pytorch as pl
14
+ from .base_v2 import Base
15
+ OLD_PL = False
16
+ except:
17
+ import pytorch_lightning as pl
18
+ OLD_PL = True
19
+ from .base import Base
20
+
21
+
22
+
23
+ class TimeKAN(Base):
24
+ handle_multivariate = True
25
+ handle_future_covariates = True
26
+ handle_categorical_variables = True
27
+ handle_quantile_loss = True
28
+ description = get_scope(handle_multivariate,handle_future_covariates,handle_categorical_variables,handle_quantile_loss)
29
+
30
+ def __init__(self,
31
+ # specific params
32
+ down_sampling_window:int,
33
+ e_layers:int,
34
+ moving_avg:int,
35
+ down_sampling_layers: int,
36
+ d_model: int,
37
+ begin_order: int,
38
+ use_norm:bool,
39
+ **kwargs)->None:
40
+
41
+
42
+
43
+
44
+ super().__init__(**kwargs)
45
+
46
+ self.save_hyperparameters(logger=False)
47
+ self.e_layers = e_layers
48
+ self.emb_past = Embedding_cat_variables(self.past_steps,self.emb_dim,self.embs_past, reduction_mode=self.reduction_mode,use_classical_positional_encoder=self.use_classical_positional_encoder,device = self.device)
49
+ #self.emb_fut = Embedding_cat_variables(self.future_steps,self.emb_dim,self.embs_fut, reduction_mode=self.reduction_mode,use_classical_positional_encoder=self.use_classical_positional_encoder,device = self.device)
50
+ emb_past_out_channel = self.emb_past.output_channels
51
+
52
+
53
+
54
+ self.res_blocks = nn.ModuleList([FrequencyDecomp( self.past_steps,down_sampling_window,down_sampling_layers) for _ in range(e_layers)])
55
+ self.add_blocks = nn.ModuleList([FrequencyMixing(d_model,self.past_steps,begin_order,down_sampling_window,down_sampling_layers) for _ in range(e_layers)])
56
+
57
+ self.preprocess = series_decomp(moving_avg)
58
+ self.enc_in = self.past_channels + emb_past_out_channel
59
+ self.project = nn.Linear(self.enc_in,d_model)
60
+ self.layer = e_layers
61
+ self.normalize_layers = torch.nn.ModuleList(
62
+ [
63
+ Normalize(self.enc_in, affine=True, non_norm=use_norm)
64
+ for i in range(down_sampling_layers + 1)
65
+ ]
66
+ )
67
+ self.predict_layer =nn. Linear(
68
+ self.past_steps,
69
+ self.future_steps,
70
+ )
71
+ self.final_layer = nn.Linear(d_model, self.mul)
72
+ self.down_sampling_layers = down_sampling_layers
73
+ self.down_sampling_window = down_sampling_window
74
+ def can_be_compiled(self):
75
+ return True#True
76
+
77
+
78
+ def __multi_level_process_inputs(self, x_enc):
79
+ down_pool = torch.nn.AvgPool1d(self.down_sampling_window)
80
+ # B,T,C -> B,C,T
81
+ x_enc = x_enc.permute(0, 2, 1)
82
+ x_enc_ori = x_enc
83
+ x_enc_sampling_list = []
84
+ x_enc_sampling_list.append(x_enc.permute(0, 2, 1))
85
+ for i in range(self.down_sampling_layers):
86
+ x_enc_sampling = down_pool(x_enc_ori)
87
+ x_enc_sampling_list.append(x_enc_sampling.permute(0, 2, 1))
88
+ x_enc_ori = x_enc_sampling
89
+ x_enc = x_enc_sampling_list
90
+ return x_enc
91
+
92
+
93
+ def forward(self, batch:dict)-> float:
94
+
95
+ x_enc = batch['x_num_past'].to(self.device)
96
+ BS = x_enc.shape[0]
97
+ if 'x_cat_past' in batch.keys():
98
+ emb_past = self.emb_past(BS,batch['x_cat_past'].to(self.device))
99
+ else:
100
+ emb_past = self.emb_past(BS,None)
101
+
102
+ x_past = torch.cat([x_enc,emb_past],2)
103
+
104
+ x_enc = self.__multi_level_process_inputs(x_past)
105
+
106
+ x_list = []
107
+ for i, x in zip(range(len(x_enc)), x_enc, ):
108
+ B, T, N = x.size()
109
+ x = self.normalize_layers[i](x, 'norm')
110
+ x = x.permute(0, 2, 1).contiguous().reshape(B * N, T, 1)
111
+ x_list.append(self.project(x.reshape(B, T, N)))
112
+
113
+
114
+
115
+ for i in range(self.layer):
116
+ x_list = self.res_blocks[i](x_list)
117
+ x_list = self.add_blocks[i](x_list)
118
+
119
+ dec_out = x_list[0]
120
+ dec_out = self.predict_layer(dec_out.permute(0, 2, 1)).permute( 0, 2, 1)
121
+ dec_out = self.final_layer(dec_out)
122
+
123
+ return dec_out.reshape(BS,self.future_steps,self.out_channels,self.mul)
@@ -0,0 +1,96 @@
1
+ ## Copyright https://github.com/thuml/Time-Series-Library/blob/main/models/TimesNet.py
2
+ ## Modified for notation alignmenet and batch structure
3
+ ## extended to what inside itransformer folder
4
+
5
+ import torch
6
+ import torch.nn as nn
7
+ import numpy as np
8
+ from .timesnet.Layers import TimesBlock
9
+ from ..data_structure.utils import beauty_string
10
+ from .utils import get_scope,get_activation,Embedding_cat_variables
11
+
12
+ try:
13
+ import lightning.pytorch as pl
14
+ from .base_v2 import Base
15
+ OLD_PL = False
16
+ except:
17
+ import pytorch_lightning as pl
18
+ OLD_PL = True
19
+ from .base import Base
20
+
21
+
22
+
23
+ class TimesNet(Base):
24
+ handle_multivariate = True
25
+ handle_future_covariates = False
26
+ handle_categorical_variables = True
27
+ handle_quantile_loss = True
28
+ description = get_scope(handle_multivariate,handle_future_covariates,handle_categorical_variables,handle_quantile_loss)
29
+
30
+ def __init__(self,
31
+ # specific params
32
+ e_layers:int,
33
+ d_model: int,
34
+ top_k: int,
35
+ d_ff: int,
36
+ num_kernels: int,
37
+ **kwargs)->None:
38
+
39
+
40
+
41
+
42
+ super().__init__(**kwargs)
43
+
44
+ self.save_hyperparameters(logger=False)
45
+ self.e_layers = e_layers
46
+ self.emb_past = Embedding_cat_variables(self.past_steps,self.emb_dim,self.embs_past, reduction_mode=self.reduction_mode,use_classical_positional_encoder=self.use_classical_positional_encoder,device = self.device)
47
+ #self.emb_fut = Embedding_cat_variables(self.future_steps,self.emb_dim,self.embs_fut, reduction_mode=self.reduction_mode,use_classical_positional_encoder=self.use_classical_positional_encoder,device = self.device)
48
+ emb_past_out_channel = self.emb_past.output_channels
49
+ #emb_fut_out_channel = self.emb_fut.output_channels
50
+
51
+ self.prepare = nn.Linear(emb_past_out_channel+self.past_channels, d_model)
52
+
53
+ self.model = nn.ModuleList([TimesBlock(self.past_steps,self.future_steps,top_k,d_model,d_ff,num_kernels) for _ in range(e_layers)])
54
+ self.layer_norm = nn.LayerNorm(d_model)
55
+
56
+ self.predict_linear = nn.Linear(self.past_steps, self.future_steps + self.past_steps)
57
+
58
+ self.projection = nn.Linear(d_model, self.out_channels*self.mul, bias=True)
59
+
60
+ def can_be_compiled(self):
61
+ return False#True
62
+
63
+ def forecast(self, x_enc, x_mark_enc, x_dec, x_mark_dec):
64
+ # Normalization from Non-stationary Transformer
65
+ #means = x_enc.mean(1, keepdim=True).detach()
66
+ #x_enc = x_enc.sub(means)
67
+ #stdev = torch.sqrt(torch.var(x_enc, dim=1, keepdim=True, unbiased=False) + 1e-5)
68
+ #x_enc = x_enc.div(stdev)
69
+
70
+ # embedding
71
+ enc_out = torch.cat([x_enc, x_mark_enc],axis=2) # [B,T,C]
72
+ enc_out = self.predict_linear(enc_out.permute(0, 2, 1)).permute(0, 2, 1) # align temporal dimension
73
+ # TimesNet
74
+ enc_out = self.prepare(enc_out)
75
+ for i in range(self.e_layers):
76
+ enc_out = self.layer_norm(self.model[i](enc_out))
77
+ # project back
78
+ dec_out = self.projection(enc_out)
79
+
80
+ # De-Normalization from Non-stationary Transformer
81
+ #dec_out = dec_out.mul((stdev[:, 0, :].unsqueeze(1).repeat(1, self.future_steps + self.past_steps, 1)))
82
+ #dec_out = dec_out.add((means[:, 0, :].unsqueeze(1).repeat(1, self.future_steps + self.past_steps, 1)))
83
+ return dec_out
84
+
85
+ def forward(self, batch:dict)-> float:
86
+
87
+ x_enc = batch['x_num_past'].to(self.device)
88
+ BS = x_enc.shape[0]
89
+ if 'x_cat_past' in batch.keys():
90
+ emb_past = self.emb_past(BS,batch['x_cat_past'].to(self.device))
91
+ else:
92
+ emb_past = self.emb_past(BS,None)
93
+
94
+ dec_out = self.forecast(x_enc, emb_past, None, None)
95
+
96
+ return dec_out[:, -self.future_steps:,:].reshape(BS,self.future_steps,self.out_channels,self.mul)
dsipts/models/base.py CHANGED
@@ -14,6 +14,7 @@ import matplotlib.pyplot as plt
14
14
  from typing import List, Union
15
15
  from .utils import QuantileLossMO, CPRS
16
16
  import torch.nn as nn
17
+ from torch.optim import Adam, AdamW, SGD, RMSprop
17
18
 
18
19
  def standardize_momentum(x,order):
19
20
  mean = torch.mean(x,1).unsqueeze(1).repeat(1,x.shape[1],1)
@@ -336,7 +337,7 @@ class Base(pl.LightningModule):
336
337
 
337
338
  :meta private:
338
339
  """
339
- if len(self._val_outputs)>0:
340
+ if (len(self._val_outputs)>0) & (self.trainer.max_epochs>0):
340
341
  ys = torch.cat([o["y"] for o in self._val_outputs])
341
342
  y_hats = torch.cat([o["y_hat"] for o in self._val_outputs])
342
343
  if self.use_quantiles:
@@ -392,8 +393,15 @@ class Base(pl.LightningModule):
392
393
  initial_loss = self.loss(y_hat[:,:,:,0], batch['y'])
393
394
  else:
394
395
  initial_loss = self.loss(y_hat, batch['y'])
396
+
397
+ if self.loss_type in ['mse','l1']:
398
+ return initial_loss
399
+
395
400
  x = batch['x_num_past'].to(self.device)
396
401
  idx_target = batch['idx_target'][0]
402
+ if idx_target is None:
403
+ beauty_string(f'Can not compute non-standard loss for non autoregressive models, if you want to use custom losses please add check=True wile initialize the time series object','info',self.verbose)
404
+ return initial_loss
397
405
  x_start = x[:,-1,idx_target].unsqueeze(1)
398
406
  y_persistence = x_start.repeat(1,self.future_steps,1)
399
407
 
dsipts/models/base_v2.py CHANGED
@@ -14,6 +14,7 @@ import matplotlib.pyplot as plt
14
14
  from typing import List, Union
15
15
  from .utils import QuantileLossMO, CPRS
16
16
  import torch.nn as nn
17
+ from torch.optim import Adam, AdamW, SGD, RMSprop
17
18
 
18
19
  def standardize_momentum(x,order):
19
20
  mean = torch.mean(x,1).unsqueeze(1).repeat(1,x.shape[1],1)
@@ -220,7 +221,7 @@ class Base(pl.LightningModule):
220
221
 
221
222
 
222
223
  if self.optim is None:
223
- optimizer = optim.Adam(self.parameters(), **self.optim_config)
224
+ optimizer = Adam(self.parameters(), **self.optim_config)
224
225
  self.initialize = True
225
226
 
226
227
  else:
@@ -237,7 +238,7 @@ class Base(pl.LightningModule):
237
238
 
238
239
  beauty_string(self.optim,'',self.verbose)
239
240
  if self.has_sam_optim:
240
- optimizer = SAM(self.parameters(), base_optimizer=torch.optim.Adam, **self.optim_config)
241
+ optimizer = SAM(self.parameters(), base_optimizer=Adam, **self.optim_config)
241
242
  else:
242
243
  optimizer = self.optim(self.parameters(), **self.optim_config)
243
244
  beauty_string(optimizer,'',self.verbose)
@@ -314,7 +315,7 @@ class Base(pl.LightningModule):
314
315
 
315
316
  :meta private:
316
317
  """
317
-
318
+
318
319
  if self.return_additional_loss:
319
320
  y_hat,score = self(batch)
320
321
  else:
@@ -335,7 +336,6 @@ class Base(pl.LightningModule):
335
336
  def on_validation_start(self):
336
337
  # reset buffer each epoch
337
338
  self._val_outputs = []
338
-
339
339
 
340
340
  def on_validation_epoch_end(self):
341
341
  """
@@ -344,7 +344,7 @@ class Base(pl.LightningModule):
344
344
  :meta private:
345
345
  """
346
346
 
347
- if len(self._val_outputs)>0:
347
+ if (len(self._val_outputs)>0) & (self.trainer.max_epochs>0):
348
348
  ys = torch.cat([o["y"] for o in self._val_outputs])
349
349
  y_hats = torch.cat([o["y_hat"] for o in self._val_outputs])
350
350
  if self.use_quantiles:
@@ -353,6 +353,7 @@ class Base(pl.LightningModule):
353
353
  idx = 0
354
354
  for i in range(ys.shape[2]):
355
355
  real = ys[0,:,i].cpu().detach().numpy()
356
+
356
357
  pred = y_hats[0,:,i,idx].cpu().detach().numpy()
357
358
  fig, ax = plt.subplots(figsize=(7,5))
358
359
  ax.plot(real,'o-',label='real')
@@ -363,7 +364,7 @@ class Base(pl.LightningModule):
363
364
  #self.log(f"example_{i}", np.stack([real, pred]).T,sync_dist=True)
364
365
  plt.close(fig)
365
366
 
366
-
367
+
367
368
  avg = self.validation_epoch_metrics/self.validation_epoch_count
368
369
 
369
370
  self.validation_epoch_metrics.zero_()
@@ -407,8 +408,17 @@ class Base(pl.LightningModule):
407
408
  initial_loss = self.loss(y_hat[:,:,:,0], batch['y'])
408
409
  else:
409
410
  initial_loss = self.loss(y_hat, batch['y'])
411
+
412
+ if self.loss_type in ['mse','l1']:
413
+ return initial_loss
414
+
410
415
  x = batch['x_num_past'].to(self.device)
416
+
411
417
  idx_target = batch['idx_target'][0]
418
+
419
+ if idx_target is None:
420
+ beauty_string(f'Can not compute non-standard loss for non autoregressive models, if you want to use custom losses please add check=True wile initialize the time series object','info',self.verbose)
421
+ return initial_loss
412
422
  x_start = x[:,-1,idx_target].unsqueeze(1)
413
423
  y_persistence = x_start.repeat(1,self.future_steps,1)
414
424
 
@@ -423,7 +433,7 @@ class Base(pl.LightningModule):
423
433
  persistence_error = (2.0-10.0*torch.clamp( torch.abs((y_persistence-x)/(0.001+torch.abs(y_persistence))),min=0.0,max=max(0.05,0.1*(1+np.log10(self.persistence_weight) ))))
424
434
  loss = torch.mean(torch.abs(x- batch['y'])*persistence_error)
425
435
 
426
- if self.loss_type == 'mda':
436
+ elif self.loss_type == 'mda':
427
437
  #import pdb
428
438
  #pdb.set_trace()
429
439
  mda = (1-torch.mean( torch.sign(torch.diff(x,axis=1))*torch.sign(torch.diff(batch['y'],axis=1))))
@@ -0,0 +1,284 @@
1
+ import torch
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+ import torch.fft
5
+
6
+
7
+ class Normalize(nn.Module):
8
+ def __init__(self, num_features: int, eps=1e-5, affine=False, subtract_last=False, non_norm=False):
9
+ """
10
+ :param num_features: the number of features or channels
11
+ :param eps: a value added for numerical stability
12
+ :param affine: if True, RevIN has learnable affine parameters
13
+ """
14
+ super(Normalize, self).__init__()
15
+ self.num_features = num_features
16
+ self.eps = eps
17
+ self.affine = affine
18
+ self.subtract_last = subtract_last
19
+ self.non_norm = non_norm
20
+ if self.affine:
21
+ self._init_params()
22
+
23
+ def forward(self, x, mode: str):
24
+ if mode == 'norm':
25
+ self._get_statistics(x)
26
+ x = self._normalize(x)
27
+ elif mode == 'denorm':
28
+ x = self._denormalize(x)
29
+ else:
30
+ raise NotImplementedError
31
+ return x
32
+
33
+ def _init_params(self):
34
+ # initialize RevIN params: (C,)
35
+ self.affine_weight = nn.Parameter(torch.ones(self.num_features))
36
+ self.affine_bias = nn.Parameter(torch.zeros(self.num_features))
37
+
38
+ def _get_statistics(self, x):
39
+ dim2reduce = tuple(range(1, x.ndim - 1))
40
+ if self.subtract_last:
41
+ self.last = x[:, -1, :].unsqueeze(1)
42
+ else:
43
+ self.mean = torch.mean(x, dim=dim2reduce, keepdim=True).detach()
44
+ self.stdev = torch.sqrt(torch.var(x, dim=dim2reduce, keepdim=True, unbiased=False) + self.eps).detach()
45
+
46
+ def _normalize(self, x):
47
+ if self.non_norm:
48
+ return x
49
+ if self.subtract_last:
50
+ x = x - self.last
51
+ else:
52
+ x = x - self.mean
53
+ x = x / self.stdev
54
+ if self.affine:
55
+ x = x * self.affine_weight
56
+ x = x + self.affine_bias
57
+ return x
58
+
59
+ def _denormalize(self, x):
60
+ if self.non_norm:
61
+ return x
62
+ if self.affine:
63
+ x = x - self.affine_bias
64
+ x = x / (self.affine_weight + self.eps * self.eps)
65
+ x = x * self.stdev
66
+ if self.subtract_last:
67
+ x = x + self.last
68
+ else:
69
+ x = x + self.mean
70
+ return x
71
+
72
+ class ChebyKANLinear(nn.Module):
73
+ def __init__(self, input_dim, output_dim, degree):
74
+ super(ChebyKANLinear, self).__init__()
75
+ self.inputdim = input_dim
76
+ self.outdim = output_dim
77
+ self.degree = degree
78
+
79
+ self.cheby_coeffs = nn.Parameter(torch.empty(input_dim, output_dim, degree + 1))
80
+ self.epsilon = 1e-7
81
+ self.pre_mul = False
82
+ self.post_mul = False
83
+ nn.init.normal_(self.cheby_coeffs, mean=0.0, std=1 / (input_dim * (degree + 1)))
84
+ self.register_buffer("arange", torch.arange(0, degree + 1, 1))
85
+
86
+ def forward(self, x):
87
+ # Since Chebyshev polynomial is defined in [-1, 1]
88
+ # We need to normalize x to [-1, 1] using tanh
89
+ # View and repeat input degree + 1 times
90
+ b,c_in = x.shape
91
+ if self.pre_mul:
92
+ mul_1 = x[:,::2]
93
+ mul_2 = x[:,1::2]
94
+ mul_res = mul_1 * mul_2
95
+ x = torch.concat([x[:,:x.shape[1]//2], mul_res])
96
+ x = x.view((b, c_in, 1)).expand(
97
+ -1, -1, self.degree + 1
98
+ ) # shape = (batch_size, inputdim, self.degree + 1)
99
+ # Apply acos
100
+ x = torch.tanh(x)
101
+ x = torch.tanh(x)
102
+ x = torch.acos(x)
103
+ # x = torch.acos(torch.clamp(x, -1 + self.epsilon, 1 - self.epsilon))
104
+ # # Multiply by arange [0 .. degree]
105
+ x = x* self.arange
106
+ # Apply cos
107
+ x = x.cos()
108
+ # Compute the Chebyshev interpolation
109
+ y = torch.einsum(
110
+ "bid,iod->bo", x, self.cheby_coeffs
111
+ ) # shape = (batch_size, outdim)
112
+ y = y.view(-1, self.outdim)
113
+ if self.post_mul:
114
+ mul_1 = y[:,::2]
115
+ mul_2 = y[:,1::2]
116
+ mul_res = mul_1 * mul_2
117
+ y = torch.concat([y[:,:y.shape[1]//2], mul_res])
118
+ return y
119
+
120
+ class ChebyKANLayer(nn.Module):
121
+ def __init__(self, in_features, out_features,order):
122
+ super().__init__()
123
+ self.fc1 = ChebyKANLinear(
124
+ in_features,
125
+ out_features,
126
+ order)
127
+ def forward(self, x):
128
+ B, N, C = x.shape
129
+ x = self.fc1(x.reshape(B*N,C))
130
+ x = x.reshape(B,N,-1).contiguous()
131
+ return x
132
+
133
+
134
+ class FrequencyDecomp(nn.Module):
135
+
136
+ def __init__(self, seq_len,down_sampling_window,down_sampling_layers):
137
+ super(FrequencyDecomp, self).__init__()
138
+ self.seq_len = seq_len
139
+ self.down_sampling_window = down_sampling_window
140
+ self.down_sampling_layers = down_sampling_layers
141
+
142
+ def forward(self, level_list):
143
+
144
+ level_list_reverse = level_list.copy()
145
+ level_list_reverse.reverse()
146
+ out_low = level_list_reverse[0]
147
+ out_high = level_list_reverse[1]
148
+ out_level_list = [out_low]
149
+ for i in range(len(level_list_reverse) - 1):
150
+ out_high_res = self.frequency_interpolation(out_low.transpose(1,2),
151
+ self.seq_len // (self.down_sampling_window ** (self.down_sampling_layers-i)),
152
+ self.seq_len // (self.down_sampling_window ** (self.down_sampling_layers-i-1))
153
+ ).transpose(1,2)
154
+ out_high_left = out_high - out_high_res
155
+ out_low = out_high
156
+ if i + 2 <= len(level_list_reverse) - 1:
157
+ out_high = level_list_reverse[i + 2]
158
+ out_level_list.append(out_high_left)
159
+ out_level_list.reverse()
160
+ return out_level_list
161
+
162
+ def frequency_interpolation(self,x,seq_len,target_len):
163
+ len_ratio = seq_len/target_len
164
+ x_fft = torch.fft.rfft(x, dim=2)
165
+ out_fft = torch.zeros([x_fft.size(0),x_fft.size(1),target_len//2+1],dtype=x_fft.dtype).to(x_fft.device)
166
+ out_fft[:,:,:seq_len//2+1] = x_fft
167
+ out = torch.fft.irfft(out_fft, dim=2)
168
+ out = out * len_ratio
169
+ return out
170
+
171
+
172
+ class FrequencyMixing(nn.Module):
173
+
174
+ def __init__(self, d_model,seq_len,begin_order,down_sampling_window,down_sampling_layers):
175
+ super(FrequencyMixing, self).__init__()
176
+ self.front_block = M_KAN(d_model,seq_len // (down_sampling_window ** (down_sampling_layers)),order=begin_order)
177
+ self.d_model = d_model
178
+ self.seq_len = seq_len
179
+ self.begin_order = begin_order
180
+ self.down_sampling_window = down_sampling_window
181
+ self.down_sampling_layers = down_sampling_layers
182
+
183
+ self.front_blocks = torch.nn.ModuleList(
184
+ [
185
+ M_KAN(d_model,
186
+ seq_len // (down_sampling_window ** (down_sampling_layers-i-1)),
187
+ order=i+begin_order+1)
188
+ for i in range(down_sampling_layers)
189
+ ])
190
+
191
+ def forward(self, level_list):
192
+ level_list_reverse = level_list.copy()
193
+ level_list_reverse.reverse()
194
+ out_low = level_list_reverse[0]
195
+ out_high = level_list_reverse[1]
196
+ out_low = self.front_block(out_low)
197
+ out_level_list = [out_low]
198
+ for i in range(len(level_list_reverse) - 1):
199
+ out_high = self.front_blocks[i](out_high)
200
+ out_high_res = self.frequency_interpolation(out_low.transpose(1,2),
201
+ self.seq_len // (self.down_sampling_window ** (self.down_sampling_layers-i)),
202
+ self.seq_len // (self.down_sampling_window ** (self.down_sampling_layers-i-1))
203
+ ).transpose(1,2)
204
+ out_high = out_high + out_high_res
205
+ out_low = out_high
206
+ if i + 2 <= len(level_list_reverse) - 1:
207
+ out_high = level_list_reverse[i + 2]
208
+ out_level_list.append(out_low)
209
+ out_level_list.reverse()
210
+ return out_level_list
211
+
212
+ def frequency_interpolation(self,x,seq_len,target_len):
213
+ len_ratio = seq_len/target_len
214
+ x_fft = torch.fft.rfft(x, dim=2)
215
+ out_fft = torch.zeros([x_fft.size(0),x_fft.size(1),target_len//2+1],dtype=x_fft.dtype).to(x_fft.device)
216
+ out_fft[:,:,:seq_len//2+1] = x_fft
217
+ out = torch.fft.irfft(out_fft, dim=2)
218
+ out = out * len_ratio
219
+ return out
220
+
221
+ class M_KAN(nn.Module):
222
+ def __init__(self,d_model,seq_len,order):
223
+ super().__init__()
224
+ self.channel_mixer = nn.Sequential(
225
+ ChebyKANLayer(d_model, d_model,order)
226
+ )
227
+ self.conv = BasicConv(d_model,d_model,kernel_size=3,degree=order,groups=d_model)
228
+ def forward(self,x):
229
+ x1 = self.channel_mixer(x)
230
+ x2 = self.conv(x)
231
+ out = x1 + x2
232
+ return out
233
+
234
+ class BasicConv(nn.Module):
235
+ def __init__(self,c_in,c_out, kernel_size, degree,stride=1, padding=0, dilation=1, groups=1, act=False, bn=False, bias=False,dropout=0.):
236
+ super(BasicConv, self).__init__()
237
+ self.out_channels = c_out
238
+ self.conv = nn.Conv1d(c_in,c_out, kernel_size=kernel_size, stride=stride, padding=kernel_size//2, dilation=dilation, groups=groups, bias=bias)
239
+ self.bn = nn.BatchNorm1d(c_out) if bn else None
240
+ self.act = nn.GELU() if act else None
241
+ self.dropout = nn.Dropout(dropout)
242
+ def forward(self, x):
243
+ if self.bn is not None:
244
+ x = self.bn(x)
245
+ x = self.conv(x.transpose(-1,-2)).transpose(-1,-2)
246
+ if self.act is not None:
247
+ x = self.act(x)
248
+ if self.dropout is not None:
249
+ x = self.dropout(x)
250
+ return x
251
+
252
+
253
+ class moving_avg(nn.Module):
254
+ """
255
+ Moving average block to highlight the trend of time series
256
+ """
257
+
258
+ def __init__(self, kernel_size, stride):
259
+ super(moving_avg, self).__init__()
260
+ self.kernel_size = kernel_size
261
+ self.avg = nn.AvgPool1d(kernel_size=kernel_size, stride=stride, padding=0)
262
+
263
+ def forward(self, x):
264
+ # padding on the both ends of time series
265
+ front = x[:, 0:1, :].repeat(1, (self.kernel_size - 1) // 2, 1)
266
+ end = x[:, -1:, :].repeat(1, (self.kernel_size - 1) // 2, 1)
267
+ x = torch.cat([front, x, end], dim=1)
268
+ x = self.avg(x.permute(0, 2, 1))
269
+ x = x.permute(0, 2, 1)
270
+ return x
271
+
272
+ class series_decomp(nn.Module):
273
+ """
274
+ Series decomposition block
275
+ """
276
+
277
+ def __init__(self, kernel_size):
278
+ super(series_decomp, self).__init__()
279
+ self.moving_avg = moving_avg(kernel_size, stride=1)
280
+
281
+ def forward(self, x):
282
+ moving_mean = self.moving_avg(x)
283
+ res = x - moving_mean
284
+ return res, moving_mean
File without changes
@@ -0,0 +1,95 @@
1
+ import torch
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+ import torch.fft
5
+
6
+
7
+ class Inception_Block_V1(nn.Module):
8
+ def __init__(self, in_channels, out_channels, num_kernels=6, init_weight=True):
9
+ super(Inception_Block_V1, self).__init__()
10
+ self.in_channels = in_channels
11
+ self.out_channels = out_channels
12
+ self.num_kernels = num_kernels
13
+ kernels = []
14
+ for i in range(self.num_kernels):
15
+ kernels.append(nn.Conv2d(in_channels, out_channels, kernel_size=2 * i + 1, padding=i))
16
+ self.kernels = nn.ModuleList(kernels)
17
+ if init_weight:
18
+ self._initialize_weights()
19
+
20
+ def _initialize_weights(self):
21
+ for m in self.modules():
22
+ if isinstance(m, nn.Conv2d):
23
+ nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
24
+ if m.bias is not None:
25
+ nn.init.constant_(m.bias, 0)
26
+
27
+ def forward(self, x):
28
+ res_list = []
29
+ for i in range(self.num_kernels):
30
+ res_list.append(self.kernels[i](x))
31
+ res = torch.stack(res_list, dim=-1).mean(-1)
32
+ return res
33
+
34
+ def FFT_for_Period(x, k=2):
35
+ # [B, T, C]
36
+ xf = torch.fft.rfft(x, dim=1)
37
+ # find period by amplitudes
38
+ frequency_list = abs(xf).mean(0).mean(-1)
39
+ frequency_list[0] = 0
40
+ _, top_list = torch.topk(frequency_list, k)
41
+ top_list = top_list.detach().cpu().numpy()
42
+ period = x.shape[1] // top_list
43
+ return period, abs(xf).mean(-1)[:, top_list]
44
+
45
+
46
+
47
+ class TimesBlock(nn.Module):
48
+ def __init__(self, seq_len,pred_len,top_k,d_model,d_ff,num_kernels):
49
+ super(TimesBlock, self).__init__()
50
+ self.seq_len = seq_len
51
+ self.pred_len = pred_len
52
+ self.k = top_k
53
+ # parameter-efficient design
54
+ self.conv = nn.Sequential(
55
+ Inception_Block_V1(d_model, d_ff,
56
+ num_kernels=num_kernels),
57
+ nn.GELU(),
58
+ Inception_Block_V1(d_ff, d_model,
59
+ num_kernels=num_kernels)
60
+ )
61
+
62
+ def forward(self, x):
63
+ B, T, N = x.size()
64
+
65
+ period_list, period_weight = FFT_for_Period(x, self.k)
66
+
67
+ res = []
68
+ for i in range(self.k):
69
+ period = period_list[i]
70
+ # padding
71
+ if (self.seq_len + self.pred_len) % period != 0:
72
+ length = (
73
+ ((self.seq_len + self.pred_len) // period) + 1) * period
74
+ padding = torch.zeros([x.shape[0], (length - (self.seq_len + self.pred_len)), x.shape[2]]).to(x.device)
75
+ out = torch.cat([x, padding], dim=1)
76
+ else:
77
+ length = (self.seq_len + self.pred_len)
78
+ out = x
79
+ # reshape
80
+ out = out.reshape(B, length // period, period,
81
+ N).permute(0, 3, 1, 2).contiguous()
82
+ # 2D conv: from 1d Variation to 2d Variation
83
+ out = self.conv(out)
84
+ # reshape back
85
+ out = out.permute(0, 2, 3, 1).reshape(B, -1, N)
86
+ res.append(out[:, :(self.seq_len + self.pred_len), :])
87
+ res = torch.stack(res, dim=-1)
88
+ # adaptive aggregation
89
+ period_weight = F.softmax(period_weight, dim=1)
90
+ period_weight = period_weight.unsqueeze(
91
+ 1).unsqueeze(1).repeat(1, T, N, 1)
92
+ res = torch.sum(res * period_weight, -1)
93
+ # residual connection
94
+ res = res + x
95
+ return res
File without changes
dsipts/version.py ADDED
@@ -0,0 +1 @@
1
+ __version__ = "1.1.15"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dsipts
3
- Version: 1.1.13
3
+ Version: 1.1.15
4
4
  Summary: Unified library for timeseries modelling
5
5
  Author-email: Andrea Gobbi <agobbi@fbk.eu>
6
6
  Project-URL: Homepage, https://github.com/DSIP-FBK/DSIPTS
@@ -398,6 +398,8 @@ and then open the url (http://127.0.0.1:43800)[http://127.0.0.1:43800]. It will
398
398
 
399
399
 
400
400
  ## TODO
401
+ [ ] some models can not work in a non-autoregressive way (target past variable is required). Relax some constraints in the forward loop can help this
402
+
401
403
  [ ] reduce test time
402
404
 
403
405
  [ ] add pre-commit hook for code checking (`ruff check --ignore E501,E722 .`)
@@ -406,15 +408,12 @@ and then open the url (http://127.0.0.1:43800)[http://127.0.0.1:43800]. It will
406
408
 
407
409
  [ ] clean code and standardize documentation
408
410
 
409
- [ ] add more sintetic data
410
-
411
411
  [ ] check all the code in the README
412
412
 
413
413
  [ ] check architecture description (which model can be used under certain assumption)
414
414
 
415
415
  [ ] complete the classification part (loss function + inference step)
416
416
 
417
-
418
417
  [ ] check D3VAE, it seems broken in some configurations
419
418
 
420
419
  [ ] add hybrid models https://www.sciencedirect.com/science/article/pii/S138912862400118X
@@ -425,11 +424,60 @@ and then open the url (http://127.0.0.1:43800)[http://127.0.0.1:43800]. It will
425
424
 
426
425
  [ ] add https://github.com/decisionintelligence/pathformer
427
426
 
428
- [x] add Duet
427
+ [ ] in 1.1.5 we split the future and past categorical variables. D3VAE &^ Diffusion to be revised
428
+
429
+ [ ] all snippet of code and notebook must be review in 1.1.5 (categorical past and future, embedding layer parameters)
429
430
 
430
- [x] add categorical support to Crossformer, Samformer
431
431
 
432
- [ ] in 1.1.5 we split the future and past categorical variables. D3VAE, Diffusion, TTM need to be revised
433
432
 
434
- [ ] all snippet of code and notebook must be review in 1.1.5 (categorical past and future, embedding layer parameters)
433
+ ## 1.1.14 (2025-12-02)
434
+ - Add CHANGELOG to the pip page
435
+ - Bug fixing for non autoregressive models
436
+ - Added TimesNet, TimeKAN
437
+ - Added 0 shot and full shot TTM
438
+ - added more option parameter to define an experiment (`split_params`, `optim_config` and `train_config`)
439
+ ## 1.1.13 (2025-12-02)
440
+
441
+ - Added weight for the WeightedRandomSampler (only for the training part)
442
+ - Bug fixing when using groups in the categorical variables
443
+ - TTM fixed for working with zeropad for shorter sequences and future covariates
444
+
445
+ ## 1.1.12 (2025-11-07)
446
+ - Bug fixing dynamo stuff for `TTM`
447
+ - Bug fixing loading weights after training process ('dynamo module can not load weights`)
448
+ - Force to not compile some models (there are piece of code that are not aligned with dynamo)
449
+ - Bug fixing test configurations
435
450
 
451
+ ## 1.1.11 (2025-11-06)
452
+ - Added `torch.compile` for better performance on recent GPU
453
+ - Stable `TTM` model according to version 1.1.5, still under debug, use at your own risk
454
+ - Bux Fixing `cprs` inference (now produces 3 quantiles: `[0.05, 0.5, 0.95]`). The `persistence_weight` is the value of `alpha` in the paper (between 0 and 1)
455
+
456
+ ## 1.1.9 (2025-09-19)
457
+ - Added `cprs` https://arxiv.org/pdf/2412.15832v1 loss function. In this case use the quantile parameter to ask for the ensembles: `quantiles = [1,2,3,4,5,6,7,8,9,10]` will create 10 ensembles. For now the inference part will return just the mean, TODO: estimate a confidence interval with the ensembles
458
+ - Added `long_lag` the L1 error will be modulated with a linear weight depending on the lag in the future: the penalization goes from `1` to `persistence_weight`
459
+
460
+ ## 1.1.8 (2025-09-12)
461
+ - Added `Simple` model (just two linear layers)
462
+
463
+ ## 1.1.7 (2025-09-08)
464
+ - bug fixing `DilatedConv`
465
+ ## 1.1.5 (2025-08-29)
466
+ - rewriting most of the modules for handling different future and past categorical variables
467
+ - extension of categorical and future covariates in almost all the models
468
+ - `uv` full management of the package
469
+ - refactoring almost all the structure and documentation
470
+
471
+ ## 1.1.4 (2025-08-22)
472
+ - added `restart: true` tro model configuration to restart the training procedure: carefurl the max_epochs should be increased if you need to retrain
473
+
474
+ ## 1.1.4 (2025-07-29)
475
+ - bug fixing tuner learning rate
476
+ - added TTM model and TimeXer
477
+ - added compatibility with newer version of lightening and torch
478
+
479
+ ## 1.1.1
480
+ - added [SAM optimizer](https://arxiv.org/pdf/2402.10198)
481
+ ```bash
482
+ python train.py --config-dir=config_test --config-name=config architecture=itransformer dataset.path=/home/agobbi/Projects/ExpTS/data train_config.dirpath=tmp inference=tmp model_configs.optim=SAM +optim_config.rho=0.5
483
+ ```
@@ -1,9 +1,10 @@
1
- dsipts/__init__.py,sha256=UWmrBJ2LLoRCKLOyTBSJAw9n31o8ZwNjLoRAax5Wll8,1694
1
+ dsipts/__init__.py,sha256=2KK6XbUewsjmQQ6-zNMKIcFP01jtcXskcwr3qZwQToE,1822
2
+ dsipts/version.py,sha256=-YHzv8tja4CPgI4M3Z_0Bj8CLGmAigr5FWkvYuc_I64,22
2
3
  dsipts/data_management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
4
  dsipts/data_management/monash.py,sha256=aZxq9FbIH6IsU8Lwou1hAokXjgOAK-wdl2VAeFg2k4M,13075
4
5
  dsipts/data_management/public_datasets.py,sha256=yXFzOZZ-X0ZG1DoqVU-zFmEGVMc2033YDQhRgYxY8ws,6793
5
6
  dsipts/data_structure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- dsipts/data_structure/data_structure.py,sha256=vOiVuTbEprXwpf8l5hk-7HP3v_r5d3YiXuQdGwo4nV0,62295
7
+ dsipts/data_structure/data_structure.py,sha256=QO2z0gtR2lv1t9DuYF3S1LSz1Ecux0CjL1G9lT5lGaY,64928
7
8
  dsipts/data_structure/modifiers.py,sha256=qlry9dfw8pEE0GrvgwROZJkJ6oPpUnjEHPIG5qIetss,7948
8
9
  dsipts/data_structure/utils.py,sha256=ZL-z_InmFUkge5kQoHSrev1t6nyve9sTYTVeA75Or-I,6689
9
10
  dsipts/models/Autoformer.py,sha256=nUQvPC_qtajLT1AHdNJmF_P3ZL01j3spkZ4ubxdGF3g,8497
@@ -17,19 +18,21 @@ dsipts/models/ITransformer.py,sha256=2WXqqEvnWH2DqRQyXfGm4Eg4_q32GFy2XnNeoTl-KmY
17
18
  dsipts/models/Informer.py,sha256=gxCdU2KkNhadyMujBA5A0eP6SPN4Q0IkEIogLYwvz5k,6970
18
19
  dsipts/models/LinearTS.py,sha256=vXaGpbbkfdpzpTEWZ1hs6QI6j3vDvevD3SyKQXo6Sdg,9151
19
20
  dsipts/models/PatchTST.py,sha256=1O09cPMg8USdkt5q6szTiz5dIY45kizsf6gt6vLKnQo,9119
20
- dsipts/models/Persistent.py,sha256=URwyaBb0M7zbPXSGMImtHlwC9XCy-OquFCwfWvn3P70,1249
21
+ dsipts/models/Persistent.py,sha256=CPHLgqAIPWbxYqzCNpxB2kh8J2-LJsvrbv9OVC72A8o,1301
21
22
  dsipts/models/RNN.py,sha256=RnsRDAQ2z5-XNaJVZd6Q7z23WvPR2uLVdi7BNQyF7QE,9685
22
23
  dsipts/models/Samformer.py,sha256=Kt7B9ID3INtFDAVKIM1LTly5-UfKCaVZ9uxAJmYv6B4,5606
23
24
  dsipts/models/Simple.py,sha256=8wRSO-gh_Z6Sl8fYMV-RIXIL0RrO5u5dDtsaq-OsKg0,3960
24
25
  dsipts/models/TFT.py,sha256=JiI90ikfP8aaR_rtczu8CyGMNLTgml13aYQifgIC_yo,13888
25
26
  dsipts/models/TIDE.py,sha256=S1KlKqFOR3jJ9DDiTqeaKvya9hYBsNHBVqwJsYX3FLU,13094
26
- dsipts/models/TTM.py,sha256=PoRDT-KYoMqv6yIOU-73E7Y2pRyd4lga0u6KrJRd5DU,6561
27
+ dsipts/models/TTM.py,sha256=CGKtO992_ty5_AX27llMd1TsvKLP8ZKpR8Xbx1F8Ws4,6625
28
+ dsipts/models/TimeKAN.py,sha256=bJEIJZIksi0jhN9ZttXezATwxJj9DkWjO1WNwDD5Fbw,4686
27
29
  dsipts/models/TimeXER.py,sha256=EkmlHfT2RegY6Ce6q8EUEV1a_WZ6SkYibnOZXqsyd_8,7111
30
+ dsipts/models/TimesNet.py,sha256=1OekvmqZidfPqoSMFsG7pK6Xcgen8IMTEu0n9ZQMEPc,3895
28
31
  dsipts/models/VQVAEA.py,sha256=sNJi8UZh-10qEIKcZK3SzhlOFUUjvqjoglzeZBFaeZM,13789
29
32
  dsipts/models/VVA.py,sha256=BnPkJ0Nzue0oShSHZVRNlf5RvT0Iwtf9bx19vLB9Nn0,11939
30
33
  dsipts/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
- dsipts/models/base.py,sha256=Gqsycy8ZXGaIVx9vvmYRpBCqdUxGE4tvC5ltgxlpEYY,19640
32
- dsipts/models/base_v2.py,sha256=03cueZExRhkJyBVIHuUPB8sjsCd5Go1HJAR81CADg-c,19896
34
+ dsipts/models/base.py,sha256=aWvtDiBnmONsJ96tgaZRewB_yrqI8yvlAlH6PdpWrLA,20099
35
+ dsipts/models/base_v2.py,sha256=BNmBQXMDnGsZABu0nOu8d3f3anNQZbgNBCwlMr-k8lQ,20346
33
36
  dsipts/models/utils.py,sha256=kjTwyktNCFMpPUy6zoleBCSKlvMvK_Jkgyh2T1OXg3E,24497
34
37
  dsipts/models/autoformer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
38
  dsipts/models/autoformer/layers.py,sha256=xHt8V1lKdD1cIvgxXdDbI_EqOz4zgOQ6LP8l7M1pAxM,13276
@@ -64,6 +67,10 @@ dsipts/models/samformer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
64
67
  dsipts/models/samformer/utils.py,sha256=62p5fzippKwZpqZBQghrHyA_ANeaFa-TC5EM4L6Q7DE,5583
65
68
  dsipts/models/tft/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
69
  dsipts/models/tft/sub_nn.py,sha256=6UDI0BvxEcF5N1_Wx3-WL0PO99k8QtI7JTsEAaosb5k,8881
70
+ dsipts/models/timekan/Layers.py,sha256=T-saVZFYHkMtbXgD8eIp2q_ZM4fcItNzw4PUo4KC-gM,10771
71
+ dsipts/models/timekan/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
+ dsipts/models/timesnet/Layers.py,sha256=Jh42klg2QFSnE1vLH35uZXp8A8xo6cvj3d3gTuvym64,3460
73
+ dsipts/models/timesnet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
74
  dsipts/models/timexer/Layers.py,sha256=-QG4a70sBQFoRoE6CfisOkKhm4kIdB21DBtQ4V-7fHw,4699
68
75
  dsipts/models/timexer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
69
76
  dsipts/models/ttm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -76,7 +83,7 @@ dsipts/models/vva/minigpt.py,sha256=bg0JddqSD322uxSGexen3nPXL_hGTsk3vNLR62d7-w8,
76
83
  dsipts/models/vva/vqvae.py,sha256=RzCQ_M9xBprp7_x20dSV3EQqlO0FjPUGWV-qdyKrQsM,19680
77
84
  dsipts/models/xlstm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
78
85
  dsipts/models/xlstm/xLSTM.py,sha256=ZKZZmffmIq1Vb71CR4GSyM8viqVx-u0FChxhcNgHub8,10081
79
- dsipts-1.1.13.dist-info/METADATA,sha256=6UZ0nHk0RoGXxxkPYCyB0w41m8LlOE5BfoiswplloXQ,24795
80
- dsipts-1.1.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
81
- dsipts-1.1.13.dist-info/top_level.txt,sha256=i6o0rf5ScFwZK21E89dSKjVNjUBkrEQpn0-Vij43748,7
82
- dsipts-1.1.13.dist-info/RECORD,,
86
+ dsipts-1.1.15.dist-info/METADATA,sha256=1i5fPSZJxFoQPkvf-PVwHf6faoD6vFhixMDucbowQdM,27477
87
+ dsipts-1.1.15.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
88
+ dsipts-1.1.15.dist-info/top_level.txt,sha256=i6o0rf5ScFwZK21E89dSKjVNjUBkrEQpn0-Vij43748,7
89
+ dsipts-1.1.15.dist-info/RECORD,,