dfm-python 0.5.55__py3-none-any.whl → 0.5.56__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.
Files changed (59) hide show
  1. dfm_python/__init__.py +19 -49
  2. dfm_python/config/__init__.py +7 -5
  3. dfm_python/config/constants.py +145 -7
  4. dfm_python/config/schema/__init__.py +12 -6
  5. dfm_python/config/schema/model.py +29 -9
  6. dfm_python/config/schema/params.py +94 -0
  7. dfm_python/config/schema/results.py +126 -31
  8. dfm_python/config/types.py +54 -17
  9. dfm_python/dataset/__init__.py +8 -47
  10. dfm_python/dataset/ddfm_dataset.py +371 -0
  11. dfm_python/{datamodule/dfm_dm.py → dataset/dfm_dataset.py} +254 -91
  12. dfm_python/dataset/time.py +97 -0
  13. dfm_python/decoder/__init__.py +3 -1
  14. dfm_python/decoder/base.py +78 -0
  15. dfm_python/decoder/linear.py +63 -59
  16. dfm_python/decoder/mlp.py +117 -126
  17. dfm_python/encoder/__init__.py +9 -9
  18. dfm_python/encoder/pca.py +6 -5
  19. dfm_python/encoder/simple_autoencoder.py +292 -0
  20. dfm_python/functional/irf.py +4 -4
  21. dfm_python/logger/__init__.py +24 -8
  22. dfm_python/logger/inference_logger.py +56 -30
  23. dfm_python/logger/train_logger.py +86 -65
  24. dfm_python/models/__init__.py +2 -10
  25. dfm_python/models/base.py +52 -210
  26. dfm_python/models/ddfm.py +730 -1736
  27. dfm_python/models/dfm.py +106 -181
  28. dfm_python/numeric/estimator.py +135 -26
  29. dfm_python/numeric/stability.py +78 -16
  30. dfm_python/numeric/statistic.py +353 -0
  31. dfm_python/numeric/validator.py +159 -7
  32. dfm_python/ssm/companion.py +4 -4
  33. dfm_python/ssm/kalman.py +2 -1
  34. dfm_python/utils/__init__.py +20 -38
  35. dfm_python/utils/checkpoint.py +295 -0
  36. dfm_python/utils/helper.py +62 -152
  37. dfm_python/utils/loss.py +100 -0
  38. dfm_python/utils/misc.py +77 -148
  39. {dfm_python-0.5.55.dist-info → dfm_python-0.5.56.dist-info}/METADATA +1 -1
  40. dfm_python-0.5.56.dist-info/RECORD +58 -0
  41. dfm_python/datamodule/__init__.py +0 -31
  42. dfm_python/datamodule/base.py +0 -618
  43. dfm_python/datamodule/ddfm_dm.py +0 -276
  44. dfm_python/datamodule/kdfm_dm.py +0 -180
  45. dfm_python/dataset/dataloader.py +0 -142
  46. dfm_python/dataset/dataset.py +0 -158
  47. dfm_python/dataset/process.py +0 -435
  48. dfm_python/encoder/simple_encoder.py +0 -474
  49. dfm_python/encoder/variational_encoder.py +0 -0
  50. dfm_python/models/kdfm.py +0 -1968
  51. dfm_python/trainer/__init__.py +0 -683
  52. dfm_python/trainer/ddfm.py +0 -656
  53. dfm_python/trainer/dfm.py +0 -154
  54. dfm_python/trainer/kdfm.py +0 -137
  55. dfm_python/utils/common.py +0 -403
  56. dfm_python/utils/tensor_utils.py +0 -199
  57. dfm_python-0.5.55.dist-info/RECORD +0 -66
  58. {dfm_python-0.5.55.dist-info → dfm_python-0.5.56.dist-info}/WHEEL +0 -0
  59. {dfm_python-0.5.55.dist-info → dfm_python-0.5.56.dist-info}/licenses/LICENSE +0 -0
dfm_python/__init__.py CHANGED
@@ -23,40 +23,36 @@ Key Features:
23
23
  - Robust handling of missing data (internal spline interpolation)
24
24
  - Automatic standardization and data clipping
25
25
 
26
- Example (Standard Lightning Pattern):
27
- >>> from dfm_python import DFM, DFMDataModule, DFMTrainer
26
+ Example:
27
+ >>> from dfm_python import DFM, DFMDataset
28
28
  >>> import pandas as pd
29
29
  >>>
30
30
  >>> # Step 1: Load and preprocess data
31
31
  >>> df = pd.read_csv('data/your_data.csv')
32
32
  >>> df_processed = df[[col for col in df.columns if col != 'date']]
33
33
  >>>
34
- >>> # Step 2: Create DataModule
35
- >>> dm = DFMDataModule(config_path='config/default.yaml', data=df_processed)
36
- >>> dm.setup()
34
+ >>> # Step 2: Create Dataset
35
+ >>> dataset = DFMDataset(config_path='config/default.yaml', data=df_processed)
37
36
  >>>
38
37
  >>> # Step 3: Create model and load config
39
38
  >>> model = DFM()
40
39
  >>> model.load_config('config/default.yaml')
41
40
  >>>
42
- >>> # Step 4: Create trainer and fit (standard Lightning pattern)
43
- >>> trainer = DFMTrainer(max_epochs=100) # DEFAULT_MAX_EPOCHS
44
- >>> trainer.fit(model, dm)
41
+ >>> # Step 4: Fit model
42
+ >>> model.fit(X=dataset.get_processed_data(), dataset=dataset)
45
43
  >>>
46
44
  >>> # Step 5: Predict
47
45
  >>> Xf, Zf = model.predict(horizon=6)
48
46
  >>>
49
- >>> # Or use DDFM (same pattern)
50
- >>> from dfm_python import DDFM, DDFMTrainer
47
+ >>> # Or use DDFM
48
+ >>> from dfm_python import DDFM, DDFMDataset
51
49
  >>>
52
- >>> dm_ddfm = DFMDataModule(config_path='config/default.yaml', data=df_processed)
53
- >>> dm_ddfm.setup()
50
+ >>> dataset_ddfm = DDFMDataset(config_path='config/default.yaml', data=df_processed)
54
51
  >>>
55
52
  >>> ddfm_model = DDFM(encoder_layers=[64, 32], num_factors=2)
56
53
  >>> ddfm_model.load_config('config/default.yaml')
57
54
  >>>
58
- >>> trainer_ddfm = DDFMTrainer(max_epochs=100) # DEFAULT_MAX_EPOCHS
59
- >>> trainer_ddfm.fit(ddfm_model, dm_ddfm)
55
+ >>> ddfm_model.train(dataset=dataset_ddfm)
60
56
  >>> Xf, Zf = ddfm_model.predict(horizon=6)
61
57
 
62
58
  Note: DFMConfig uses frequency dict to specify series (column names -> frequencies).
@@ -65,7 +61,7 @@ Note: DFMConfig uses frequency dict to specify series (column names -> frequenci
65
61
  For detailed documentation, see the README.md file and the tutorial notebooks/scripts.
66
62
  """
67
63
 
68
- __version__ = "0.5.55"
64
+ __version__ = "0.5.56"
69
65
 
70
66
  # ============================================================================
71
67
  # PUBLIC API DEFINITION
@@ -92,20 +88,15 @@ from .config import (
92
88
  from .config import DFMConfig
93
89
 
94
90
  # Results
95
- from .config import DFMResult, DDFMResult, KDFMResult, BaseResult
91
+ from .config import DFMResult, DDFMResult, BaseResult
96
92
 
97
93
  # Utilities (from utils/ subpackage)
98
94
  from .utils.metric import calculate_rmse
99
95
 
100
- # DataModule classes (includes both Lightning and custom implementations)
96
+ # Dataset classes
101
97
  # Users can import these directly from dfm_python
102
- from .datamodule import (
103
- DFMDataModule,
104
- DDFMDataModule, # DDFM-specific DataModule
105
- KDFMDataModule, # KDFM-specific DataModule
106
- DDFMDataset, # DDFM Dataset class (usually not needed directly)
107
- KDFMDataset, # KDFM Dataset class (usually not needed directly)
108
- )
98
+ from .dataset.dfm_dataset import DFMDataset
99
+ from .dataset.ddfm_dataset import DDFMDataset
109
100
 
110
101
  # Model implementations
111
102
  from .models.base import BaseFactorModel
@@ -114,9 +105,6 @@ from .models.dfm import DFM
114
105
  # DDFM high-level API (PyTorch is mandatory)
115
106
  from .models.ddfm import DDFM
116
107
 
117
- # KDFM high-level API
118
- from .models.kdfm import KDFM
119
-
120
108
  __all__ = [
121
109
  # Core classes
122
110
  'DFM',
@@ -126,7 +114,7 @@ __all__ = [
126
114
  'ConfigSource', 'YamlSource',
127
115
  'make_config_source',
128
116
  # Low-level API (functional interface - advanced usage)
129
- 'BaseResult', 'DFMResult', 'DDFMResult', 'KDFMResult', 'calculate_rmse',
117
+ 'BaseResult', 'DFMResult', 'DDFMResult', 'calculate_rmse',
130
118
  ]
131
119
 
132
120
  # DDFM high-level API (PyTorch is mandatory)
@@ -134,27 +122,9 @@ __all__.extend([
134
122
  'DDFM', # High-level API class
135
123
  ])
136
124
 
137
- # KDFM high-level API
138
- __all__.extend([
139
- 'KDFM', # High-level API class
140
- ])
141
-
142
- # Lightning modules (mandatory dependency)
125
+ # Dataset classes
143
126
  __all__.extend([
144
- 'DFMDataModule',
145
- 'DDFMDataModule', # DDFM-specific DataModule
146
- 'KDFMDataModule', # KDFM-specific DataModule
147
- 'DDFMDataset', # DDFM Dataset class (usually not needed directly)
148
- 'KDFMDataset', # KDFM Dataset class (usually not needed directly)
127
+ 'DFMDataset', # DFM Dataset class
128
+ 'DDFMDataset', # DDFM Dataset class
149
129
  ])
150
130
 
151
- # Trainer classes (mandatory dependency)
152
- from .trainer import DFMTrainer, DDFMTrainer, KDFMTrainer
153
-
154
- __all__.extend([
155
- 'DFMTrainer',
156
- 'DDFMTrainer',
157
- 'KDFMTrainer',
158
- ])
159
-
160
-
@@ -8,8 +8,9 @@ Note: Series are specified via frequency dict mapping column names to frequencie
8
8
  """
9
9
 
10
10
  from .schema import (
11
- BaseModelConfig, DFMConfig, DDFMConfig, KDFMConfig,
12
- BaseResult, DFMResult, DDFMResult, KDFMResult, FitParams,
11
+ BaseModelConfig, DFMConfig, DDFMConfig,
12
+ BaseResult, DFMResult, DDFMResult,
13
+ DFMFitParams, DDFMFitParams, FitParams, # FitParams is backward compatibility alias
13
14
  )
14
15
  # DEFAULT_BLOCK_NAME is imported lazily where needed to avoid circular imports
15
16
  from .constants import (
@@ -105,11 +106,12 @@ __all__ = [
105
106
  'BaseModelConfig', 'BaseResult',
106
107
  # 'DEFAULT_BLOCK_NAME', # Removed to avoid circular import - import directly from functional.dfm_block
107
108
  # Model-specific configs (from schema.py)
108
- 'DFMConfig', 'DDFMConfig', 'KDFMConfig',
109
+ 'DFMConfig', 'DDFMConfig',
109
110
  # Parameter overrides
110
- 'FitParams',
111
+ 'DFMFitParams', 'DDFMFitParams',
112
+ 'FitParams', # Backward compatibility alias
111
113
  # Model-specific results (from results.py)
112
- 'DFMResult', 'DDFMResult', 'KDFMResult',
114
+ 'DFMResult', 'DDFMResult',
113
115
  # Utilities
114
116
  'validate_frequency',
115
117
  # IO
@@ -26,8 +26,10 @@ DEFAULT_MIN_DELTA = 1e-6 # Minimum change for improvement
26
26
  MIN_EIGENVALUE = 1e-8 # Minimum eigenvalue for positive definite matrices
27
27
  MIN_DIAGONAL_VARIANCE = 1e-8 # Minimum variance for diagonal elements
28
28
  MIN_OBSERVATION_NOISE = 1e-4 # Minimum observation noise for measurement error (used in EM updates)
29
+ DEFAULT_DDFM_OBSERVATION_NOISE = 1e-15 # Default observation noise for DDFM state-space (matches original TensorFlow)
29
30
  MIN_FACTOR_VARIANCE = 1e-10 # Minimum variance for factors
30
31
  MIN_STD = 1e-8 # Minimum standard deviation
32
+ MIN_STD_FOR_SCALE_CHECK = 1e-10 # Minimum standard deviation for scale ratio computation (more lenient than MIN_STD)
31
33
  DEFAULT_VARIANCE_FALLBACK = 1.0 # Default variance fallback value for numerical stability
32
34
 
33
35
  # Maximum eigenvalues
@@ -44,8 +46,11 @@ DEFAULT_CLEAN_INF = MAX_EIGENVALUE # Default value for Inf replacement in clean
44
46
  # Identity matrix defaults
45
47
  DEFAULT_IDENTITY_SCALE = 1.0 # Default scale for create_scaled_identity(n, 1.0)
46
48
  DEFAULT_ZERO_VALUE = 0.0 # Default zero value for explicit zero assignments
47
- DEFAULT_XAVIER_GAIN = 1.0 # Default gain for Xavier initialization
48
- DEFAULT_OUTPUT_LAYER_GAIN = 0.1 # Default gain for output layer Xavier initialization (smaller for stability)
49
+ DEFAULT_INF_VALUE = float('inf') # Default infinity value for loss/scale comparisons
50
+ DEFAULT_XAVIER_GAIN = 1.0 # Default gain for Xavier initialization (matches TensorFlow GlorotNormal)
51
+ DEFAULT_OUTPUT_LAYER_GAIN = 1.0 # Default gain for output layer Xavier initialization (matches original TensorFlow DDFM GlorotNormal for all layers)
52
+ # NOTE: Original TensorFlow DDFM uses GlorotNormal (gain=1.0) for all layers including output layer.
53
+ # Updated to match original TensorFlow behavior to address training divergence (encoder weights too small, near-zero factors).
49
54
 
50
55
  # Companion matrix initialization defaults
51
56
  DEFAULT_INIT_SCALE = 0.01 # Default initialization scale for companion matrix B and C matrices
@@ -59,6 +64,41 @@ DEFAULT_REGULARIZATION = 1e-6 # Default regularization value
59
64
  DEFAULT_CLIP_THRESHOLD = 10.0 # Default clipping threshold (in standard deviations)
60
65
  DEFAULT_DATA_CLIP_THRESHOLD = 100.0 # Default data clipping threshold
61
66
 
67
+ # Scale validation thresholds (for DDFM scale alignment checks)
68
+ DEFAULT_SCALE_RATIO_MAX = 10.0 # Maximum acceptable scale ratio (prediction std / data std)
69
+ DEFAULT_SCALE_RATIO_MIN = 0.1 # Minimum acceptable scale ratio (prediction std / data std)
70
+ DEFAULT_STANDARDIZATION_MEAN_THRESHOLD = 0.1 # Maximum acceptable absolute mean for standardized data (mean should be ≈0)
71
+ DEFAULT_STANDARDIZATION_STD_MIN = 0.1 # Minimum acceptable std for standardized data (std should be ≈1)
72
+ DEFAULT_STANDARDIZATION_STD_MAX = 10.0 # Maximum acceptable std for standardized data (std should be ≈1)
73
+ DEFAULT_STANDARDIZED_TARGET_STD = 1.0 # Target std for standardized data (std should be ≈1.0 for StandardScaler)
74
+
75
+ # Variance collapse diagnostics thresholds (for DDFM variance collapse detection)
76
+ DEFAULT_VARIANCE_COLLAPSE_THRESHOLD = 0.1 # Prediction std threshold for variance collapse detection (std < 0.1 indicates collapse)
77
+ DEFAULT_FACTOR_COLLAPSE_THRESHOLD = 0.01 # Factor magnitude threshold for factor collapse detection (|mean| < 0.01 indicates collapse)
78
+ DEFAULT_BATCHNORM_SUPPRESSION_THRESHOLD = 0.01 # BatchNorm running_var threshold for signal suppression detection (var < 0.01 indicates suppression)
79
+ DEFAULT_TIMESTEP_COLLAPSE_THRESHOLD = 0.1 # Per-time-step std threshold for localized collapse detection (std < 0.1 indicates collapse)
80
+ DEFAULT_TIMESTEP_COLLAPSE_RATIO_THRESHOLD = 0.5 # Ratio threshold for localized collapse (ratio > 0.5 indicates widespread collapse)
81
+ DEFAULT_EXPECTED_FACTOR_MAGNITUDE_MIN = 0.1 # Expected minimum factor magnitude (for warning messages)
82
+ DEFAULT_EXPECTED_FACTOR_MAGNITUDE_MAX = 1.0 # Expected maximum factor magnitude (for warning messages)
83
+
84
+ # DDFM reproduction target values (for debugging and diagnostics)
85
+ DEFAULT_TARGET_PREDICTION_STD = 1.0 # Target prediction std for standardized data (should be ~1.0 for StandardScaler)
86
+ DEFAULT_VARIANCE_COLLAPSE_STD = 0.03 # Observed variance collapse std (std ~0.03 vs target ~1.0)
87
+ DEFAULT_TARGET_CONVERGENCE_ITERATIONS = 10 # Target convergence iterations for exchange_rate dataset (TensorFlow reference)
88
+ DEFAULT_TARGET_DDFM_LOSS = 0.56 # Target DDFM training loss for exchange_rate dataset (TensorFlow reference)
89
+ DEFAULT_DDFM_LOSS_MULTIPLIER = 1.8 # Current loss multiplier vs target (1.00 vs 0.56 = 1.8x)
90
+
91
+ # Logging precision constants
92
+ DEFAULT_SCALE_LOG_PRECISION = 6 # Default precision for scale logging format strings (e.g., .6f)
93
+ DEFAULT_TIME_LOG_PRECISION = 2 # Default precision for time logging format strings (e.g., .2f)
94
+ DEFAULT_LOSS_LOG_PRECISION = 6 # Default precision for loss/delta logging format strings (e.g., .6f)
95
+
96
+ # Time conversion constants
97
+ SECONDS_PER_MINUTE = 60 # Seconds per minute (for time conversion)
98
+
99
+ # Logging level constants
100
+ LOGGING_DEBUG_LEVEL = 10 # logging.DEBUG level for conditional checks
101
+
62
102
  # ============================================================================
63
103
  # Training Defaults
64
104
  # ============================================================================
@@ -68,15 +108,41 @@ DEFAULT_MAX_ITER = 100 # Default maximum EM iterations (general)
68
108
  DEFAULT_EM_MAX_ITER = 5000 # Default maximum EM iterations (DFM-specific)
69
109
  DEFAULT_MAX_EPOCHS = 100 # Default maximum training epochs
70
110
  DEFAULT_MAX_MCMC_ITER = 200 # Default maximum MCMC iterations
111
+ DEFAULT_N_MC_SAMPLES = 10 # Default number of MC samples per MCMC iteration for DDFM denoising training (matches original TensorFlow epochs=10 default, per experiment/config/model/ddfm.yaml)
112
+ DEFAULT_FACTOR_ORDER = 1 # Default factor order for DDFM (AR(1) dynamics)
113
+ DEFAULT_AR_ORDER_2 = 2 # Default AR order 2 for DDFM forecast (AR(2) dynamics)
71
114
 
72
115
  # Batch size defaults
73
116
  DEFAULT_BATCH_SIZE = 32 # Default batch size for neural networks
74
- DEFAULT_DDFM_BATCH_SIZE = 100 # Default batch size for DDFM
117
+ DEFAULT_DDFM_WINDOW_SIZE = 100 # Default window size (time-step batch size) for DDFM
118
+ DEFAULT_DDFM_BATCH_SIZE = 100 # Default batch size for DDFM (matches original TensorFlow batch_size=100)
119
+
120
+ # DDFM target interpolation defaults
121
+ DEFAULT_MIN_TARGET_INTERPOLATE_RATIO = 0.3 # Default minimum target interpolate ratio threshold for DDFM (ratio of missing target values above which interpolation is skipped)
122
+
123
+ # MCMC training defaults (for DDFM sequential MC processing)
124
+ DEFAULT_MCMC_EPOCHS = 1 # Default epochs per MC sample (MCMC training pattern: one epoch per MC sample)
125
+ DEFAULT_MCMC_VERBOSE = 0 # Default verbosity for MCMC training (silent training)
126
+
127
+ # Placeholder defaults (for DDFM placeholder MC dataset)
128
+ DEFAULT_PLACEHOLDER_MC_SAMPLES = 1 # Minimal MC samples for placeholder dataset (replaced after on_train_start)
129
+ DEFAULT_PLACEHOLDER_DATA_SHAPE_T = 100 # Default time steps for placeholder data shape
130
+ DEFAULT_PLACEHOLDER_DATA_SHAPE_N = 10 # Default number of series for placeholder data shape
131
+ DEFAULT_PLACEHOLDER_SEED = 42 # Seed for placeholder random state (common test value, placeholder gets replaced)
132
+ DEFAULT_NUM_WORKERS = 0 # Default number of workers for DataLoader (0 = single-threaded)
133
+ DEFAULT_CUDA_DEVICE_INDEX = 0 # Default CUDA device index for GPU operations (0 = first GPU)
134
+
135
+ # Initialization sample size defaults
136
+ DEFAULT_KDFM_INIT_SAMPLE_SIZE = 100 # Default sample size for KDFM initialization (first N rows used for initialize_from_data)
75
137
 
76
138
  # Learning rate defaults
77
139
  DEFAULT_LEARNING_RATE = 0.001 # Default learning rate
78
140
  DEFAULT_DDFM_LEARNING_RATE = 0.005 # Default learning rate for DDFM
79
141
 
142
+ # Autoencoder training defaults (matches original TensorFlow pattern)
143
+ DEFAULT_AUTOENCODER_FIT_EPOCHS = 1 # Number of epochs per MC sample (matches original TensorFlow: epochs=1 per autoencoder.fit() call)
144
+ DEFAULT_AUTOENCODER_FIT_VERBOSE = 0 # Verbosity level for autoencoder.fit() (0 = silent, matches original TensorFlow verbose=0)
145
+
80
146
  # Gradient clipping
81
147
  DEFAULT_GRAD_CLIP_VAL = 1.0 # Default gradient clipping value
82
148
 
@@ -86,6 +152,22 @@ DEFAULT_WEIGHT_DECAY = 0.0 # Default weight decay (L2 regularization)
86
152
  # Learning rate decay
87
153
  DEFAULT_LR_DECAY_RATE = 0.96 # Default exponential decay rate for learning rate
88
154
 
155
+ # Optimizer defaults
156
+ VALID_OPTIMIZERS = {'Adam', 'AdamW', 'SGD'} # Valid optimizer types for DDFM
157
+
158
+ # Adam optimizer defaults
159
+ DEFAULT_ADAM_BETA1 = 0.9 # Default beta1 (momentum decay) for Adam optimizer
160
+ DEFAULT_ADAM_BETA2 = 0.999 # Default beta2 (squared gradient decay) for Adam optimizer
161
+ DEFAULT_ADAM_EPS = 1e-7 # Default epsilon for Adam optimizer (matches TensorFlow default for DDFM compatibility)
162
+ DEFAULT_PYTORCH_ADAM_EPS = 1e-8 # PyTorch default epsilon for Adam optimizer (for reference)
163
+
164
+ # Batch normalization defaults (matching TensorFlow/Keras defaults)
165
+ DEFAULT_BATCH_NORM_MOMENTUM = 0.99 # TensorFlow/Keras BatchNormalization default momentum
166
+ DEFAULT_BATCH_NORM_EPS = 1e-3 # TensorFlow/Keras BatchNormalization default epsilon
167
+
168
+ # Random seed defaults
169
+ DEFAULT_RANDOM_SEED_MAX = 2**31 # Maximum value for random seed generation (2147483647, 32-bit signed integer max)
170
+
89
171
  # Loss function defaults
90
172
  DEFAULT_HUBER_DELTA = 1.0 # Default delta parameter for Huber loss
91
173
  HUBER_QUADRATIC_COEFF = 0.5 # Quadratic coefficient for Huber loss (0.5 * a^2 term)
@@ -115,7 +197,11 @@ CHOLESKY_LOG_DET_FACTOR = 2.0 # Factor for log determinant computation from Cho
115
197
  # ============================================================================
116
198
 
117
199
  # Encoder layer defaults
118
- DEFAULT_ENCODER_LAYERS = [64, 32] # Default encoder layer sizes
200
+ DEFAULT_ENCODER_LAYERS = [16, 4] # Default encoder layer sizes (matches experiment config and ddfm.py default parameter)
201
+ DEFAULT_NUM_FACTORS = 3 # Default number of factors for DDFM
202
+ DEFAULT_ACTIVATION = 'relu' # Default activation function for DDFM
203
+ DEFAULT_DECODER = 'linear' # Default decoder type for DDFM
204
+ DEFAULT_USE_BATCH_NORM = True # Default batch normalization setting for DDFM
119
205
 
120
206
  # ============================================================================
121
207
  # Data Processing Defaults
@@ -131,8 +217,8 @@ DEFAULT_START_DATE = datetime(2000, 1, 1)
131
217
  # Default window size for DDFM
132
218
  DEFAULT_WINDOW_SIZE = 100
133
219
  DEFAULT_TENT_KERNEL_SIZE = 5 # Default tent kernel size for slower-frequency series aggregation
134
- # Note: DEFAULT_BATCH_SIZE is defined above (line 52) as 32 for general neural networks
135
- # Use DEFAULT_DDFM_BATCH_SIZE (100) for DDFM-specific batch size
220
+ # Note: DEFAULT_BATCH_SIZE is defined above (line 88) as 32 for general neural networks
221
+ # Use DEFAULT_DDFM_WINDOW_SIZE (100) for DDFM-specific window size (time-step batch size)
136
222
 
137
223
  # Warning/display limits
138
224
  MAX_WARNING_ITEMS = 5 # Maximum number of items to show in warning messages
@@ -142,6 +228,9 @@ MAX_ERROR_ITEMS = 20 # Maximum number of items to show in error message details
142
228
  DEFAULT_MIN_OBS = 5 # Default minimum observations for estimation
143
229
  DEFAULT_MIN_OBS_IDIO = 5 # Default minimum observations for idio estimation
144
230
  DEFAULT_MIN_OBS_VAR = 7 # Minimum observations for VAR estimation (order + 5)
231
+ DEFAULT_MIN_OBS_PRETRAIN = 50 # Minimum observations for DDFM pre-training without interpolation
232
+ DEFAULT_MULT_EPOCH_PRETRAIN = 1 # Multiplier for DDFM pre-training epochs
233
+ DEFAULT_PRETRAIN_EPOCHS = 200 # Default number of epochs for DDFM pre-training (matching original paper)
145
234
 
146
235
  # Dimension validation bounds
147
236
  MIN_TIME_STEPS = 1 # Minimum number of time steps (T) required for data
@@ -149,7 +238,9 @@ MIN_VARIABLES = 1 # Minimum number of variables (N) required for data
149
238
  MIN_DDFM_TIME_STEPS = 2 # Minimum number of time steps (T) required for DDFM training (DDFM-specific, different from general MIN_TIME_STEPS=1)
150
239
  MIN_DDFM_DATASET_SIZE_WARNING = 10 # Minimum dataset size (T) below which DDFM denoising training warns about potential instability
151
240
  MIN_ITER_FOR_DELTA_COMPUTATION = 1 # Minimum iteration count required before computing delta (MSE change) in DDFM denoising training
241
+ DEFAULT_MIN_ITER_FOR_CONVERGENCE_CHECK = 2 # Minimum iteration count required before checking convergence in DDFM (check from iteration 3 onwards)
152
242
  MIN_EPS_SHAPE_FOR_IDIO = 1 # Minimum eps shape dimension required for idiosyncratic component processing in DDFM
243
+ MIN_SHAPE_FOR_AR2 = 2 # Minimum shape dimension for AR(2) forecast (need at least 2 previous time steps)
153
244
 
154
245
  # Idiosyncratic component defaults
155
246
  DEFAULT_IDIO_STD = 0.1 # Default idiosyncratic standard deviation (when estimation fails)
@@ -328,6 +419,7 @@ __all__ = [
328
419
  'MIN_OBSERVATION_NOISE',
329
420
  'MIN_FACTOR_VARIANCE',
330
421
  'MIN_STD',
422
+ 'MIN_STD_FOR_SCALE_CHECK',
331
423
  'MAX_EIGENVALUE',
332
424
  'DEFAULT_EIGENVALUE_MAX_MAGNITUDE',
333
425
  'DEFAULT_EIGENVALUE_WARN_THRESHOLD',
@@ -343,19 +435,53 @@ __all__ = [
343
435
  'DEFAULT_REGULARIZATION',
344
436
  'DEFAULT_CLIP_THRESHOLD',
345
437
  'DEFAULT_DATA_CLIP_THRESHOLD',
438
+ 'DEFAULT_SCALE_RATIO_MAX',
439
+ 'DEFAULT_SCALE_RATIO_MIN',
440
+ 'DEFAULT_STANDARDIZATION_MEAN_THRESHOLD',
441
+ 'DEFAULT_STANDARDIZATION_STD_MIN',
442
+ 'DEFAULT_STANDARDIZATION_STD_MAX',
443
+ 'DEFAULT_STANDARDIZED_TARGET_STD',
444
+ 'DEFAULT_TARGET_PREDICTION_STD',
445
+ 'DEFAULT_VARIANCE_COLLAPSE_STD',
446
+ 'DEFAULT_TARGET_CONVERGENCE_ITERATIONS',
447
+ 'DEFAULT_TARGET_DDFM_LOSS',
448
+ 'DEFAULT_DDFM_LOSS_MULTIPLIER',
449
+ 'DEFAULT_SCALE_LOG_PRECISION',
450
+ 'DEFAULT_TIME_LOG_PRECISION',
451
+ 'DEFAULT_LOSS_LOG_PRECISION',
452
+ 'SECONDS_PER_MINUTE',
346
453
  'MIN_CONDITION_NUMBER',
347
454
  'MAX_CONDITION_NUMBER',
348
455
  # Training
349
456
  'DEFAULT_MAX_ITER',
350
457
  'DEFAULT_MAX_EPOCHS',
351
458
  'DEFAULT_MAX_MCMC_ITER',
459
+ 'DEFAULT_N_MC_SAMPLES',
352
460
  'DEFAULT_BATCH_SIZE', # General neural network default (32)
353
- 'DEFAULT_DDFM_BATCH_SIZE', # DDFM-specific default (100)
461
+ 'DEFAULT_DDFM_WINDOW_SIZE', # DDFM-specific window size default (100)
462
+ 'DEFAULT_DDFM_BATCH_SIZE', # DDFM batch size default (100)
463
+ 'DEFAULT_PLACEHOLDER_MC_SAMPLES', # Placeholder MC samples default (1)
464
+ 'DEFAULT_PLACEHOLDER_DATA_SHAPE_T', # Placeholder data shape T default (100)
465
+ 'DEFAULT_PLACEHOLDER_DATA_SHAPE_N', # Placeholder data shape N default (10)
466
+ 'DEFAULT_PLACEHOLDER_SEED', # Placeholder random seed default (42)
467
+ 'DEFAULT_NUM_WORKERS', # DataLoader num_workers default (0)
468
+ 'DEFAULT_CUDA_DEVICE_INDEX', # CUDA device index default (0 = first GPU)
469
+ 'DEFAULT_KDFM_INIT_SAMPLE_SIZE', # KDFM initialization sample size default (100)
354
470
  'DEFAULT_LEARNING_RATE',
355
471
  'DEFAULT_DDFM_LEARNING_RATE',
472
+ 'DEFAULT_AUTOENCODER_FIT_EPOCHS',
473
+ 'DEFAULT_AUTOENCODER_FIT_VERBOSE',
356
474
  'DEFAULT_GRAD_CLIP_VAL',
357
475
  'DEFAULT_WEIGHT_DECAY',
358
476
  'DEFAULT_LR_DECAY_RATE',
477
+ 'VALID_OPTIMIZERS',
478
+ 'DEFAULT_ADAM_BETA1',
479
+ 'DEFAULT_ADAM_BETA2',
480
+ 'DEFAULT_ADAM_EPS',
481
+ 'DEFAULT_TENSORFLOW_ADAM_EPS',
482
+ 'DEFAULT_BATCH_NORM_MOMENTUM',
483
+ 'DEFAULT_BATCH_NORM_EPS',
484
+ 'DEFAULT_RANDOM_SEED_MAX',
359
485
  'DEFAULT_HUBER_DELTA',
360
486
  'HUBER_QUADRATIC_COEFF',
361
487
  'DEFAULT_DDFM_CLIP_RANGE_DEEP',
@@ -368,7 +494,13 @@ __all__ = [
368
494
  'DEFAULT_STRUCTURAL_DIAG_SCALE',
369
495
  'DEFAULT_CHOLESKY_EPS',
370
496
  # Architecture
497
+ 'DEFAULT_FACTOR_ORDER',
498
+ 'DEFAULT_AR_ORDER_2',
371
499
  'DEFAULT_ENCODER_LAYERS',
500
+ 'DEFAULT_NUM_FACTORS',
501
+ 'DEFAULT_ACTIVATION',
502
+ 'DEFAULT_DECODER',
503
+ 'DEFAULT_USE_BATCH_NORM',
372
504
  # Data processing
373
505
  'DEFAULT_NAN_METHOD',
374
506
  'DEFAULT_NAN_K',
@@ -378,12 +510,18 @@ __all__ = [
378
510
  'DEFAULT_MIN_OBS',
379
511
  'DEFAULT_MIN_OBS_IDIO',
380
512
  'DEFAULT_MIN_OBS_VAR',
513
+ 'DEFAULT_MIN_OBS_PRETRAIN',
514
+ 'DEFAULT_MULT_EPOCH_PRETRAIN',
515
+ 'DEFAULT_PRETRAIN_EPOCHS',
381
516
  # Dimension validation
382
517
  'MIN_TIME_STEPS',
383
518
  'MIN_VARIABLES',
519
+ 'MIN_SHAPE_FOR_AR2',
384
520
  'MIN_DDFM_TIME_STEPS',
521
+ 'MIN_SHAPE_FOR_AR2',
385
522
  'MIN_DDFM_DATASET_SIZE_WARNING',
386
523
  'MIN_ITER_FOR_DELTA_COMPUTATION',
524
+ 'DEFAULT_MIN_ITER_FOR_CONVERGENCE_CHECK',
387
525
  'MIN_EPS_SHAPE_FOR_IDIO',
388
526
  'DEFAULT_IDIO_STD',
389
527
  'DEFAULT_IDIO_RHO0',
@@ -1,17 +1,23 @@
1
1
  """Configuration schema package for DFM models.
2
2
 
3
3
  This package contains:
4
- - model.py: BaseModelConfig, DFMConfig, DDFMConfig, KDFMConfig - model configurations
5
- - results.py: BaseResult, DFMResult, DDFMResult, KDFMResult - result structures
4
+ - model.py: BaseModelConfig, DFMConfig, DDFMConfig - model configurations
5
+ - results.py: BaseResult, DFMResult, DDFMResult - result structures
6
6
 
7
7
  Note: Series are specified via frequency dict mapping column names to frequencies.
8
8
  """
9
9
 
10
- from .model import BaseModelConfig, DFMConfig, DDFMConfig, KDFMConfig
11
- from .results import BaseResult, DFMResult, DDFMResult, KDFMResult, FitParams
10
+ from .model import BaseModelConfig, DFMConfig, DDFMConfig
11
+ from .results import BaseResult, DFMResult, DDFMResult
12
+ from .params import DFMFitParams, DDFMFitParams
13
+
14
+ # Backward compatibility alias
15
+ FitParams = DFMFitParams
12
16
 
13
17
  __all__ = [
14
- 'BaseModelConfig', 'DFMConfig', 'DDFMConfig', 'KDFMConfig',
15
- 'BaseResult', 'DFMResult', 'DDFMResult', 'KDFMResult', 'FitParams',
18
+ 'BaseModelConfig', 'DFMConfig', 'DDFMConfig',
19
+ 'BaseResult', 'DFMResult', 'DDFMResult',
20
+ 'DFMFitParams', 'DDFMFitParams',
21
+ 'FitParams', # Backward compatibility alias
16
22
  ]
17
23
 
@@ -46,7 +46,7 @@ from ..constants import (
46
46
  DEFAULT_LEARNING_RATE,
47
47
  DEFAULT_MAX_EPOCHS,
48
48
  DEFAULT_BATCH_SIZE,
49
- DEFAULT_DDFM_BATCH_SIZE,
49
+ DEFAULT_DDFM_WINDOW_SIZE,
50
50
  DEFAULT_GRAD_CLIP_VAL,
51
51
  DEFAULT_REGULARIZATION_SCALE,
52
52
  DEFAULT_STRUCTURAL_REG_WEIGHT,
@@ -495,24 +495,25 @@ class DDFMConfig(BaseModelConfig):
495
495
  - Series definitions via frequency dict (column names -> frequencies)
496
496
  """
497
497
  # ========================================================================
498
- # Neural Network Training Parameters
498
+ # Neural Network Training Hyper Parameters
499
499
  # ========================================================================
500
500
  encoder_layers: Optional[List[int]] = None # Hidden layer dimensions for encoder (default: [64, 32])
501
501
  num_factors: Optional[int] = None # Number of factors (inferred from config if None)
502
502
  activation: str = 'relu' # Activation function ('tanh', 'relu', 'sigmoid', default: 'relu' to match original DDFM)
503
503
  use_batch_norm: bool = True # Use batch normalization in encoder (default: True)
504
504
  learning_rate: float = 0.001 # Learning rate for Adam optimizer (default: 0.001)
505
- epochs: int = 100 # Number of training epochs (default: 100)
506
- batch_size: int = 100 # Batch size for training (default: 100 to match original DDFM)
505
+ n_mc_samples: int = 10 # Number of MC samples per MCMC iteration (default: 10, matching original TensorFlow epochs=10 default, per experiment/config/model/ddfm.yaml)
506
+ window_size: int = 100 # Window size (time-step batch size) for training (default: 100 to match original DDFM)
507
507
  # Note: factor_order removed - factors always use AR(1) dynamics (simplified)
508
508
  use_idiosyncratic: bool = True # Model idio components with AR(1) dynamics (default: True)
509
509
  min_obs_idio: int = 5 # Minimum observations for idio AR(1) estimation (default: 5)
510
510
 
511
511
  # Additional training parameters
512
- max_iter: int = DEFAULT_MAX_MCMC_ITER # Maximum MCMC iterations for iterative factor extraction
512
+ max_epoch: int = DEFAULT_MAX_MCMC_ITER # Maximum number of epochs (MCMC iterations). One epoch = one MCMC iteration (MC sampling → training → convergence check)
513
513
  tolerance: float = DEFAULT_TOLERANCE # Convergence tolerance for MCMC iterations
514
514
  disp: int = 10 # Display frequency for training progress
515
515
  seed: Optional[int] = None # Random seed for reproducibility
516
+ lags_input: int = 0 # Number of lags of inputs on encoder (default 0, matching original TensorFlow DDFM)
516
517
 
517
518
 
518
519
  # ========================================================================
@@ -523,21 +524,40 @@ class DDFMConfig(BaseModelConfig):
523
524
  def _extract_ddfm(cls, data: Dict[str, Any]) -> Dict[str, Any]:
524
525
  """Extract DDFM-specific parameters from config dict."""
525
526
  # Don't extract base params here - they're already in base_params from from_dict
527
+ from ..constants import DEFAULT_N_MC_SAMPLES
526
528
  ddfm_params = cls._extract_params(data, {
527
529
  'encoder_layers': None,
528
530
  'num_factors': None,
529
531
  'activation': 'relu',
530
532
  'use_batch_norm': True,
531
533
  'learning_rate': DEFAULT_LEARNING_RATE,
532
- 'epochs': DEFAULT_MAX_EPOCHS,
533
- 'batch_size': DEFAULT_DDFM_BATCH_SIZE,
534
+ 'epochs': DEFAULT_N_MC_SAMPLES, # Backward compatibility: map 'epochs' to n_mc_samples
535
+ 'n_mc_samples': DEFAULT_N_MC_SAMPLES, # Preferred name: number of MC samples per MCMC iteration
536
+ 'window_size': DEFAULT_DDFM_WINDOW_SIZE, # Window size (time-step batch size) for training
534
537
  'use_idiosyncratic': True,
535
538
  'min_obs_idio': DEFAULT_MIN_OBS_IDIO,
536
- 'max_iter': DEFAULT_MAX_MCMC_ITER,
539
+ 'max_epoch': DEFAULT_MAX_MCMC_ITER, # Maximum epochs (MCMC iterations)
537
540
  'tolerance': DEFAULT_TOLERANCE,
538
541
  'disp': DEFAULT_DISP,
539
542
  'seed': None,
543
+ 'lags_input': 0, # Number of lags (default 0, matching original TensorFlow)
540
544
  })
545
+ # Map 'epochs' from config to 'n_mc_samples' for clarity (backward compatibility)
546
+ # Always remove 'epochs' if present (even if n_mc_samples is also present)
547
+ if 'epochs' in ddfm_params:
548
+ if 'n_mc_samples' not in ddfm_params:
549
+ ddfm_params['n_mc_samples'] = ddfm_params['epochs']
550
+ ddfm_params.pop('epochs') # Always remove 'epochs' to avoid passing it to constructor
551
+ # Map 'batch_size' from config to 'window_size' for backward compatibility
552
+ if 'batch_size' in ddfm_params:
553
+ if 'window_size' not in ddfm_params:
554
+ ddfm_params['window_size'] = ddfm_params['batch_size']
555
+ ddfm_params.pop('batch_size') # Always remove 'batch_size' to avoid passing it to constructor
556
+ # Only accept 'max_epoch' parameter (no backward compatibility)
557
+ # Remove any old parameter names if present
558
+ ddfm_params.pop('max_iter', None)
559
+ ddfm_params.pop('max_iterations', None)
560
+ ddfm_params.pop('max_mc_iter', None)
541
561
  return ddfm_params
542
562
 
543
563
  @classmethod
@@ -546,7 +566,7 @@ class DDFMConfig(BaseModelConfig):
546
566
  result = DFMConfig.from_dict(data)
547
567
  if isinstance(result, DDFMConfig):
548
568
  return result
549
- from ..utils.errors import ConfigurationError
569
+ from ...utils.errors import ConfigurationError
550
570
  raise ConfigurationError(
551
571
  "Expected DDFMConfig but got DFMConfig",
552
572
  details=f"Result type: {type(result).__name__}, expected: DDFMConfig"
@@ -0,0 +1,94 @@
1
+ """Model parameters for DFM and DDFM.
2
+
3
+ This module defines dataclasses for storing fit-time parameters and state-space parameters.
4
+ """
5
+
6
+ from dataclasses import dataclass
7
+ import numpy as np
8
+ from typing import Optional
9
+
10
+
11
+ @dataclass
12
+ class DFMFitParams:
13
+ """Fit-time parameter overrides for DFM estimation.
14
+
15
+ This dataclass allows overriding configuration parameters at fit time
16
+ without modifying the configuration object itself.
17
+
18
+ Based on DFM.fit() usage, these parameters are passed to the EM algorithm.
19
+
20
+ Attributes
21
+ ----------
22
+ max_iter : int, optional
23
+ Maximum EM iterations (overrides config.max_iter)
24
+ Used in: kalman_filter.em(max_iter=...)
25
+ threshold : float, optional
26
+ Convergence threshold (overrides config.threshold)
27
+ Used in: kalman_filter.em(threshold=...)
28
+ regularization_scale : float, optional
29
+ Regularization scale for matrix operations (overrides EM config)
30
+ Note: This affects EMConfig.regularization and EMConfig.matrix_regularization
31
+ """
32
+ max_iter: Optional[int] = None
33
+ threshold: Optional[float] = None
34
+ regularization_scale: Optional[float] = None
35
+
36
+ @dataclass
37
+ class DDFMTrainingState:
38
+ """Training state for DDFM model.
39
+
40
+ Stores the current state of DDFM training, including convergence status,
41
+ loss, factors, and residuals. Used for checkpointing and resuming training.
42
+
43
+ Attributes
44
+ ----------
45
+ num_iter : int
46
+ Current iteration number in MCMC training loop.
47
+ loss_now : float, optional
48
+ Current training loss value.
49
+ converged : bool
50
+ Whether training has converged.
51
+ eps : np.ndarray, optional
52
+ Idiosyncratic residuals (T x num_target_series).
53
+ factors : np.ndarray, optional
54
+ Extracted factors (n_mc_samples x T x num_factors) or (T x num_factors).
55
+ last_neurons : np.ndarray, optional
56
+ Last layer neurons for MLP decoder (n_mc_samples x T x num_neurons) or (T x num_neurons).
57
+ For linear decoder, this equals factors.
58
+ """
59
+ num_iter: int = 0
60
+ loss_now: Optional[float] = None
61
+ converged: bool = False
62
+ eps: Optional[np.ndarray] = None
63
+ factors: Optional[np.ndarray] = None
64
+ last_neurons: Optional[np.ndarray] = None
65
+
66
+ @dataclass
67
+ class DDFMFitParams:
68
+ """State-space model parameters for DDFM (created during fit).
69
+
70
+ These parameters are computed during DDFM.build_state_space() and represent
71
+ the fitted state-space model structure. Naming follows original paper conventions.
72
+
73
+ Parameters
74
+ ----------
75
+ F : np.ndarray
76
+ Transition matrix (m x m) - VAR(1) dynamics for factors (A in paper)
77
+ Q : np.ndarray
78
+ Process noise covariance (m x m) - innovation covariance (W in original code)
79
+ mu_0 : np.ndarray
80
+ Initial state mean (m,) - initial factor values
81
+ Sigma_0 : np.ndarray
82
+ Initial state covariance (m x m) - initial uncertainty
83
+ H : np.ndarray
84
+ Observation matrix (N x m) - decoder weights (measurement equation, theta in paper)
85
+ R : np.ndarray
86
+ Observation noise covariance (N x N) - typically diagonal, small values
87
+ """
88
+ F: np.ndarray # Transition matrix (m x m) - A in paper
89
+ Q: np.ndarray # Process noise covariance (m x m) - W in original code
90
+ mu_0: np.ndarray # Initial state mean (m,)
91
+ Sigma_0: np.ndarray # Initial state covariance (m x m)
92
+ H: np.ndarray # Observation matrix (N x m) - theta in paper
93
+ R: np.ndarray # Observation noise covariance (N x N)
94
+