dfm-python 0.3.1__py3-none-any.whl → 0.4.2__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 (67) hide show
  1. dfm_python/__init__.py +94 -115
  2. dfm_python/config/__init__.py +42 -12
  3. dfm_python/config/{io.py → adapter.py} +188 -198
  4. dfm_python/{core → config}/results.py +130 -80
  5. dfm_python/config/schema.py +585 -430
  6. dfm_python/{core/structure.py → config/utils.py} +103 -13
  7. dfm_python/data/__init__.py +52 -0
  8. dfm_python/data/dataloader.py +97 -0
  9. dfm_python/data/dataset.py +154 -0
  10. dfm_python/data/transformation.py +313 -0
  11. dfm_python/data/utils.py +339 -0
  12. dfm_python/encoder/__init__.py +39 -0
  13. dfm_python/encoder/base.py +111 -0
  14. dfm_python/encoder/pca.py +296 -0
  15. dfm_python/encoder/vae.py +550 -0
  16. dfm_python/lightning/__init__.py +50 -0
  17. dfm_python/lightning/callbacks.py +0 -0
  18. dfm_python/lightning/data_module.py +558 -0
  19. dfm_python/lightning/ddfm_module.py +580 -0
  20. dfm_python/lightning/dfm_module.py +466 -0
  21. dfm_python/lightning/utils.py +0 -0
  22. dfm_python/logger/__init__.py +53 -0
  23. dfm_python/logger/inference_logger.py +313 -0
  24. dfm_python/logger/logger.py +120 -0
  25. dfm_python/logger/train_logger.py +533 -0
  26. dfm_python/models/__init__.py +13 -8
  27. dfm_python/models/base.py +185 -48
  28. dfm_python/models/ddfm.py +1381 -765
  29. dfm_python/models/dfm.py +1078 -119
  30. dfm_python/models/estimation.py +372 -0
  31. dfm_python/nowcast/__init__.py +28 -0
  32. dfm_python/nowcast/dataview.py +143 -0
  33. dfm_python/nowcast/helpers.py +358 -0
  34. dfm_python/{nowcasting → nowcast}/nowcast.py +55 -537
  35. dfm_python/nowcast/utils.py +289 -0
  36. dfm_python/ssm/__init__.py +47 -0
  37. dfm_python/ssm/em.py +775 -0
  38. dfm_python/ssm/kalman.py +604 -0
  39. dfm_python/ssm/utils.py +380 -0
  40. dfm_python/trainer/__init__.py +739 -0
  41. dfm_python/trainer/ddfm.py +177 -0
  42. dfm_python/trainer/dfm.py +155 -0
  43. dfm_python/utils/__init__.py +159 -26
  44. dfm_python/utils/data.py +542 -0
  45. dfm_python/{core → utils}/diagnostics.py +11 -87
  46. dfm_python/utils/helpers.py +454 -0
  47. dfm_python/utils/statespace.py +1297 -0
  48. dfm_python/{core → utils}/time.py +373 -0
  49. {dfm_python-0.3.1.dist-info → dfm_python-0.4.2.dist-info}/METADATA +17 -9
  50. dfm_python-0.4.2.dist-info/RECORD +52 -0
  51. dfm_python/api/__init__.py +0 -44
  52. dfm_python/api/model_api.py +0 -1148
  53. dfm_python/api/session_api.py +0 -402
  54. dfm_python/core/__init__.py +0 -139
  55. dfm_python/core/em.py +0 -1385
  56. dfm_python/core/estimation.py +0 -553
  57. dfm_python/core/helpers.py +0 -1338
  58. dfm_python/core/state_space.py +0 -993
  59. dfm_python/dataloader/__init__.py +0 -30
  60. dfm_python/dataloader/loader.py +0 -763
  61. dfm_python/dataloader/preprocess.py +0 -11
  62. dfm_python/nowcasting/__init__.py +0 -13
  63. dfm_python/utils/convert.py +0 -342
  64. dfm_python/utils/loss.py +0 -184
  65. dfm_python-0.3.1.dist-info/RECORD +0 -32
  66. {dfm_python-0.3.1.dist-info → dfm_python-0.4.2.dist-info}/WHEEL +0 -0
  67. {dfm_python-0.3.1.dist-info → dfm_python-0.4.2.dist-info}/licenses/LICENSE +0 -0
dfm_python/__init__.py CHANGED
@@ -7,7 +7,7 @@ This package implements a comprehensive Dynamic Factor Model framework with supp
7
7
  - Expectation-Maximization (EM) algorithm for parameter estimation
8
8
  - Kalman filtering and smoothing for factor extraction
9
9
  - News decomposition for nowcasting
10
- - Deep Dynamic Factor Models (DDFM) with nonlinear encoders (optional, requires PyTorch)
10
+ - Deep Dynamic Factor Models (DDFM) with nonlinear encoders (requires PyTorch)
11
11
 
12
12
  The package implements a clock-based approach to mixed-frequency DFMs, where all latent
13
13
  factors (global and block-level) are synchronized to a common "clock" frequency, typically
@@ -18,47 +18,56 @@ Note: Higher frequencies (daily, weekly) than the clock are not supported. If an
18
18
  has a frequency faster than the clock, a ValueError will be raised.
19
19
 
20
20
  Key Features:
21
- - Unified configuration system (YAML with Hydra/OmegaConf, or direct DFMConfig objects)
21
+ - Hydra-based configuration (YAML files) - primary configuration method
22
+ - Expects preprocessed data from users - package applies internal transformations automatically
22
23
  - Flexible block structure for factor modeling
23
- - Robust handling of missing data
24
- - Comprehensive transformation support
24
+ - Robust handling of missing data (internal spline interpolation)
25
+ - Automatic standardization and data clipping
25
26
  - News decomposition for forecast updates
26
27
 
27
- Example (High-level API - Recommended):
28
- >>> import dfm_python as dfm
29
- >>> # Linear DFM
30
- >>> model = dfm.DFM()
28
+ Example (Standard Lightning Pattern):
29
+ >>> from dfm_python import DFM, DFMDataModule, DFMTrainer
30
+ >>> import polars as pl
31
+ >>>
32
+ >>> # Step 1: Load and preprocess data
33
+ >>> df = pl.read_csv('data/sample_data.csv')
34
+ >>> df_processed = df.select([col for col in df.columns if col != 'date'])
35
+ >>>
36
+ >>> # Step 2: Create DataModule
37
+ >>> dm = DFMDataModule(config_path='config/default.yaml', data=df_processed)
38
+ >>> dm.setup()
39
+ >>>
40
+ >>> # Step 3: Create model and load config
41
+ >>> model = DFM()
31
42
  >>> model.load_config('config/default.yaml')
32
- >>> model.load_data('data/sample_data.csv')
33
- >>> model.train(max_iter=100)
43
+ >>>
44
+ >>> # Step 4: Create trainer and fit (standard Lightning pattern)
45
+ >>> trainer = DFMTrainer(max_epochs=100)
46
+ >>> trainer.fit(model, dm)
47
+ >>>
48
+ >>> # Step 5: Predict
34
49
  >>> Xf, Zf = model.predict(horizon=6)
35
50
  >>>
36
- >>> # Or use DDFM (separate class)
37
- >>> ddfm_model = dfm.DDFM(encoder_layers=[64, 32], num_factors=2)
51
+ >>> # Or use DDFM (same pattern)
52
+ >>> from dfm_python import DDFM, DDFMTrainer
53
+ >>>
54
+ >>> dm_ddfm = DFMDataModule(config_path='config/default.yaml', data=df_processed)
55
+ >>> dm_ddfm.setup()
56
+ >>>
57
+ >>> ddfm_model = DDFM(encoder_layers=[64, 32], num_factors=2)
38
58
  >>> ddfm_model.load_config('config/default.yaml')
39
- >>> ddfm_model.load_data('data/sample_data.csv')
40
- >>> ddfm_model.train(epochs=100)
59
+ >>>
60
+ >>> trainer_ddfm = DDFMTrainer(max_epochs=100)
61
+ >>> trainer_ddfm.fit(ddfm_model, dm_ddfm)
41
62
  >>> Xf, Zf = ddfm_model.predict(horizon=6)
42
63
 
43
- Example (Low-level API - For advanced usage):
44
- >>> from dfm_python import DFM, DFMConfig, SeriesConfig
45
- >>> from dfm_python.dataloader import load_data # Preferred import
46
- >>> # Option 1: Load from YAML
47
- >>> config = load_config('config.yaml')
48
- >>> # Option 2: Create directly
49
- >>> config = DFMConfig(
50
- ... series=[SeriesConfig(frequency='m', transformation='lin', blocks=[1], series_id='series1')],
51
- ... block_names=['Global']
52
- ... )
53
- >>> X, Time, _ = load_data('data.csv', config) # or use database adapter
54
- >>> model = DFM()
55
- >>> result = model.fit(X, config)
56
- >>> factors = result.Z # Extract estimated factors
64
+ Note: DFMConfig and SeriesConfig are internal implementation details.
65
+ Users should use Hydra YAML configuration files instead.
57
66
 
58
67
  For detailed documentation, see the README.md file and the tutorial notebooks/scripts.
59
68
  """
60
69
 
61
- __version__ = "0.3.1"
70
+ __version__ = "0.4.2"
62
71
 
63
72
  # ============================================================================
64
73
  # PUBLIC API DEFINITION
@@ -68,126 +77,96 @@ __version__ = "0.3.1"
68
77
  # Internal reorganization should not break these imports.
69
78
  #
70
79
  # Public API categories:
71
- # 1. Configuration: DFMConfig, SeriesConfig, BlockConfig, Params, config sources
80
+ # 1. Configuration: DFMConfig, SeriesConfig, config sources
72
81
  # 2. High-level API: DFM, DDFM, module-level convenience functions
73
- # 3. Core utilities: DFMCore, run_kf, TimeIndex, diagnostics
82
+ # 3. Core utilities: DFMLinear, TimeIndex, diagnostics
74
83
  # 4. Models: BaseFactorModel, DFMLinear, DDFM (low-level)
75
84
  # 5. Nowcasting: Nowcast, result classes, para_const
76
- # 6. Data & Results: DFMResult, transform_data
85
+ # 6. Data & Results: DFMResult
77
86
  # ============================================================================
78
87
 
79
88
  # Configuration (from config/ subpackage)
80
89
  from .config import (
81
- DFMConfig, SeriesConfig, BlockConfig, Params, DEFAULT_GLOBAL_BLOCK_NAME,
90
+ DEFAULT_BLOCK_NAME,
82
91
  ConfigSource, YamlSource, DictSource, HydraSource,
83
92
  MergedConfigSource, make_config_source,
84
93
  )
94
+ # Internal imports (for backward compatibility, but not recommended)
95
+ from .config import DFMConfig, SeriesConfig # Internal use only
85
96
 
86
97
  # Data utilities
87
- from .dataloader import transform_data
88
98
 
89
99
  # Results
90
- from .core import DFMResult
91
-
92
- # Core utilities (from core/ subpackage)
93
- from .core import calculate_rmse, diagnose_series, print_series_diagnosis
94
- from .core.state_space import run_kf, skf, fis, miss_data
95
- # DFMCore is now an alias for DFMLinear (backward compatibility)
96
- from .models.dfm import DFMLinear
97
- DFMCore = DFMLinear
100
+ from .config.results import DFMResult, DDFMResult, BaseResult
101
+
102
+ # Utilities (from utils/ subpackage)
103
+ from .utils.diagnostics import diagnose_series, print_series_diagnosis
104
+ from .utils.time import calculate_rmse
105
+
106
+ # PyTorch Lightning modules (mandatory dependency)
107
+ # Users can import these directly from dfm_python
108
+ from .lightning import (
109
+ DFMDataModule,
110
+ DFMDataset, # Dataset class (usually not needed directly)
111
+ KalmanFilter, # Module class
112
+ EMAlgorithm, # Module class
113
+ )
98
114
 
99
- # Nowcasting (already in nowcasting/ subpackage)
100
- from .nowcasting import (
115
+ # Nowcasting (from nowcast/ subpackage)
116
+ from .nowcast import (
101
117
  Nowcast,
102
- para_const,
103
118
  NowcastResult,
119
+ )
120
+ from .nowcast.helpers import (
121
+ para_const,
104
122
  NewsDecompResult,
105
123
  BacktestResult,
106
124
  )
107
125
 
108
- # High-level API (from api/ subpackage)
109
- from .api import (
110
- DFM, _dfm_instance, from_yaml, from_spec, from_spec_df, from_dict,
111
- load_config, load_data, load_pickle, train, predict, plot, reset, create_model
112
- )
113
-
114
126
  # Model implementations
115
127
  from .models.base import BaseFactorModel
116
- from .models.dfm import DFMLinear
117
-
118
- # DDFM high-level API and low-level model (both optional, requires PyTorch)
119
- try:
120
- from .api import DDFM as DDFMAPI, _ddfm_instance
121
- from .api import load_config_ddfm, load_data_ddfm, train_ddfm, predict_ddfm, plot_ddfm, reset_ddfm
122
- from .models.ddfm import DDFM as DDFMModel
123
- _has_ddfm = True
124
- # Export high-level API as DDFM
125
- DDFM = DDFMAPI
126
- except ImportError:
127
- _has_ddfm = False
128
- DDFM = None # type: ignore
129
- DDFMModel = None # type: ignore
130
- load_config_ddfm = None # type: ignore
131
- load_data_ddfm = None # type: ignore
132
- train_ddfm = None # type: ignore
133
- predict_ddfm = None # type: ignore
134
- plot_ddfm = None # type: ignore
135
- reset_ddfm = None # type: ignore
136
-
137
- # Expose properties as module-level attributes
138
- # Use property-like access via functions or direct attribute access
139
- # Since 'config' conflicts with the config module, we'll use a different approach
140
- # Users can access: dfm.get_config(), dfm.get_data(), dfm.get_result()
141
- def get_config():
142
- """Get current configuration."""
143
- return _dfm_instance.config
144
-
145
- def get_data():
146
- """Get current data matrix."""
147
- return _dfm_instance.data
148
-
149
- def get_time():
150
- """Get current time index."""
151
- return _dfm_instance.time
152
-
153
- def get_result():
154
- """Get training result."""
155
- return _dfm_instance.result
156
-
157
- def get_original_data():
158
- """Get original (untransformed) data matrix."""
159
- return _dfm_instance.original_data
128
+ from .models.dfm import DFMLinear, DFM
129
+
130
+ # DDFM high-level API and low-level model (PyTorch is mandatory)
131
+ from .models.ddfm import DDFM, DDFMModel
160
132
 
161
133
  __all__ = [
162
134
  # Core classes
163
- 'DFMConfig', 'SeriesConfig', 'BlockConfig', 'Params', 'DFM', 'DFMCore', 'Nowcast',
135
+ 'DFM', 'DFMLinear', 'Nowcast',
164
136
  # Model base and implementations
165
- 'BaseFactorModel', 'DFMLinear',
137
+ 'BaseFactorModel',
166
138
  # Nowcast result classes
167
139
  'NowcastResult', 'NewsDecompResult', 'BacktestResult',
168
140
  # Constants
169
- 'DEFAULT_GLOBAL_BLOCK_NAME',
141
+ 'DEFAULT_BLOCK_NAME',
170
142
  # Config sources
171
143
  'ConfigSource', 'YamlSource', 'DictSource', 'HydraSource',
172
144
  'MergedConfigSource', 'make_config_source',
173
- # High-level API (module-level - recommended)
174
- 'load_config',
175
- 'load_data', 'load_pickle', 'train', 'predict', 'plot', 'reset', 'create_model',
176
- 'get_config', 'get_data', 'get_time', 'get_result', 'get_original_data',
177
- # Convenience constructors (cleaner API)
178
- 'from_yaml', 'from_spec', 'from_spec_df', 'from_dict',
179
145
  # Low-level API (functional interface - advanced usage)
180
- 'transform_data',
181
- 'DFMResult', 'calculate_rmse', 'diagnose_series', 'print_series_diagnosis',
182
- 'run_kf', 'skf', 'fis', 'miss_data',
183
- 'para_const', # Internal utility, kept for backward compatibility
146
+ 'BaseResult', 'DFMResult', 'DDFMResult', 'calculate_rmse', 'diagnose_series', 'print_series_diagnosis',
147
+ 'para_const', # Internal utility for nowcasting
184
148
  ]
185
149
 
186
- # Add DDFM high-level API and convenience functions if available
187
- if _has_ddfm:
188
- __all__.extend([
189
- 'DDFM', # High-level API class
190
- 'load_config_ddfm', 'load_data_ddfm', 'train_ddfm',
191
- 'predict_ddfm', 'plot_ddfm', 'reset_ddfm'
192
- ])
150
+ # DDFM high-level API (PyTorch is mandatory)
151
+ __all__.extend([
152
+ 'DDFM', # High-level API class
153
+ 'DDFMModel', # Low-level implementation (used internally)
154
+ ])
155
+
156
+ # Lightning modules (mandatory dependency)
157
+ __all__.extend([
158
+ 'DFMDataModule',
159
+ 'DFMDataset', # Dataset class (usually not needed directly)
160
+ 'KalmanFilter', # Module class
161
+ 'EMAlgorithm', # Module class
162
+ ])
163
+
164
+ # Trainer classes (mandatory dependency)
165
+ from .trainer import DFMTrainer, DDFMTrainer
166
+
167
+ __all__.extend([
168
+ 'DFMTrainer',
169
+ 'DDFMTrainer',
170
+ ])
171
+
193
172
 
@@ -1,35 +1,65 @@
1
1
  """Configuration subpackage for DFM.
2
2
 
3
3
  This subpackage provides:
4
- - Schema (DFMConfig, SeriesConfig, BlockConfig, Params) in schema.py
5
- - IO (ConfigSource, YamlSource, etc.) in io.py
4
+ - Schema (DFMConfig, SeriesConfig) in schema.py
5
+ - IO (ConfigSource, YamlSource, etc.) in adapter.py
6
6
  """
7
7
 
8
8
  from .schema import (
9
- DFMConfig, SeriesConfig, BlockConfig, Params,
10
- DEFAULT_GLOBAL_BLOCK_NAME,
11
- validate_frequency, validate_transformation,
9
+ BaseModelConfig, DFMConfig, DDFMConfig, SeriesConfig,
10
+ DEFAULT_BLOCK_NAME,
12
11
  )
13
- from .io import (
12
+ from .results import BaseResult, DFMResult, DDFMResult, FitParams
13
+ from .utils import validate_frequency, validate_transformation
14
+ from .adapter import (
14
15
  ConfigSource,
15
16
  YamlSource,
16
17
  DictSource,
17
18
  HydraSource,
18
19
  MergedConfigSource,
19
20
  make_config_source,
20
- from_spec,
21
- _load_config_from_dataframe,
22
- _write_series_blocks_yaml,
21
+ # Note: from_spec is in models/dfm.py, not in adapter
22
+ # Note: Private functions (_load_config_from_dataframe, _write_series_blocks_yaml)
23
+ # are available from adapter module but not exported as public API
24
+ )
25
+ from .utils import (
26
+ FREQUENCY_HIERARCHY,
27
+ PERIODS_PER_YEAR,
28
+ get_periods_per_year,
29
+ get_annual_factor,
30
+ compute_idio_chain_lengths,
31
+ get_tent_weights_for_pair,
32
+ generate_tent_weights,
33
+ generate_R_mat,
34
+ get_aggregation_structure,
35
+ group_series_by_frequency,
23
36
  )
24
37
 
25
38
  __all__ = [
26
39
  # Schema
27
- 'DFMConfig', 'SeriesConfig', 'BlockConfig', 'Params',
28
- 'DEFAULT_GLOBAL_BLOCK_NAME',
40
+ 'BaseModelConfig', 'DFMConfig', 'DDFMConfig', 'SeriesConfig',
41
+ 'DEFAULT_BLOCK_NAME',
42
+ # Parameter overrides
43
+ 'FitParams',
44
+ # Results
45
+ 'BaseResult', 'DFMResult', 'DDFMResult',
46
+ # Utilities
29
47
  'validate_frequency', 'validate_transformation',
30
48
  # IO
31
49
  'ConfigSource', 'YamlSource', 'DictSource',
32
50
  'HydraSource', 'MergedConfigSource', 'make_config_source',
33
- 'from_spec', '_load_config_from_dataframe', '_write_series_blocks_yaml',
51
+ # Frequency and aggregation utilities
52
+ 'FREQUENCY_HIERARCHY',
53
+ 'PERIODS_PER_YEAR',
54
+ 'get_periods_per_year',
55
+ 'get_annual_factor',
56
+ 'compute_idio_chain_lengths',
57
+ 'get_tent_weights_for_pair',
58
+ 'generate_tent_weights',
59
+ 'generate_R_mat',
60
+ 'get_aggregation_structure',
61
+ 'group_series_by_frequency',
62
+ # Note: Private functions (_load_config_from_dataframe, _write_series_blocks_yaml)
63
+ # are available from adapter module but not exported as public API
34
64
  ]
35
65