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 +4 -1
- dsipts/data_structure/data_structure.py +83 -22
- dsipts/models/Persistent.py +2 -0
- dsipts/models/TTM.py +5 -2
- dsipts/models/TimeKAN.py +123 -0
- dsipts/models/TimesNet.py +96 -0
- dsipts/models/base.py +9 -1
- dsipts/models/base_v2.py +17 -7
- dsipts/models/timekan/Layers.py +284 -0
- dsipts/models/timekan/__init__.py +0 -0
- dsipts/models/timesnet/Layers.py +95 -0
- dsipts/models/timesnet/__init__.py +0 -0
- dsipts/version.py +1 -0
- {dsipts-1.1.13.dist-info → dsipts-1.1.15.dist-info}/METADATA +56 -8
- {dsipts-1.1.13.dist-info → dsipts-1.1.15.dist-info}/RECORD +17 -10
- {dsipts-1.1.13.dist-info → dsipts-1.1.15.dist-info}/WHEEL +0 -0
- {dsipts-1.1.13.dist-info → dsipts-1.1.15.dist-info}/top_level.txt +0 -0
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
|
-
|
|
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
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
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 =
|
|
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)
|
dsipts/models/Persistent.py
CHANGED
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
|
-
|
|
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
|
|
dsipts/models/TimeKAN.py
ADDED
|
@@ -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 =
|
|
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=
|
|
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
|
-
|
|
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.
|
|
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
|
-
[
|
|
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
|
-
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
32
|
-
dsipts/models/base_v2.py,sha256=
|
|
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.
|
|
80
|
-
dsipts-1.1.
|
|
81
|
-
dsipts-1.1.
|
|
82
|
-
dsipts-1.1.
|
|
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,,
|
|
File without changes
|
|
File without changes
|