dfm-python 0.4.0__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.
- dfm_python/__init__.py +77 -141
- dfm_python/config/__init__.py +18 -18
- dfm_python/config/{io.py → adapter.py} +188 -198
- dfm_python/config/results.py +36 -11
- dfm_python/config/schema.py +375 -149
- dfm_python/config/utils.py +479 -25
- dfm_python/data/__init__.py +52 -0
- dfm_python/data/dataloader.py +97 -0
- dfm_python/data/dataset.py +154 -0
- dfm_python/{transformations/transformers.py → data/transformation.py} +40 -47
- dfm_python/{transformations → data}/utils.py +2 -2
- dfm_python/encoder/__init__.py +8 -2
- dfm_python/encoder/base.py +111 -0
- dfm_python/encoder/pca.py +142 -3
- dfm_python/encoder/vae.py +262 -3
- dfm_python/lightning/__init__.py +9 -7
- dfm_python/lightning/data_module.py +364 -170
- dfm_python/lightning/ddfm_module.py +33 -6
- dfm_python/logger/__init__.py +2 -0
- dfm_python/logger/inference_logger.py +60 -17
- dfm_python/logger/logger.py +13 -3
- dfm_python/logger/train_logger.py +269 -45
- dfm_python/models/__init__.py +8 -20
- dfm_python/models/base.py +168 -27
- dfm_python/models/ddfm.py +1046 -572
- dfm_python/models/dfm.py +676 -314
- dfm_python/models/estimation.py +42 -22
- dfm_python/nowcast/helpers.py +30 -226
- dfm_python/nowcast/nowcast.py +0 -3
- dfm_python/nowcast/utils.py +9 -10
- dfm_python/ssm/em.py +395 -108
- dfm_python/ssm/kalman.py +1 -1
- dfm_python/ssm/utils.py +2 -1
- dfm_python/trainer/__init__.py +727 -8
- dfm_python/trainer/ddfm.py +149 -168
- dfm_python/trainer/dfm.py +130 -128
- dfm_python/utils/__init__.py +19 -49
- dfm_python/utils/data.py +28 -192
- dfm_python/utils/helpers.py +19 -98
- dfm_python/utils/statespace.py +43 -72
- {dfm_python-0.4.0.dist-info → dfm_python-0.4.2.dist-info}/METADATA +7 -1
- dfm_python-0.4.2.dist-info/RECORD +52 -0
- dfm_python/config/params.py +0 -202
- dfm_python/config/structure.py +0 -457
- dfm_python/transformations/__init__.py +0 -35
- dfm_python/transformations/sktime.py +0 -40
- dfm_python-0.4.0.dist-info/RECORD +0 -53
- {dfm_python-0.4.0.dist-info → dfm_python-0.4.2.dist-info}/WHEEL +0 -0
- {dfm_python-0.4.0.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 (
|
|
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,73 +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
|
-
-
|
|
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
|
-
-
|
|
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 (
|
|
28
|
-
>>>
|
|
29
|
-
>>>
|
|
30
|
-
>>> from sktime.transformations.compose import ColumnTransformer
|
|
28
|
+
Example (Standard Lightning Pattern):
|
|
29
|
+
>>> from dfm_python import DFM, DFMDataModule, DFMTrainer
|
|
30
|
+
>>> import polars as pl
|
|
31
31
|
>>>
|
|
32
|
-
>>> #
|
|
33
|
-
>>>
|
|
34
|
-
>>>
|
|
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
35
|
>>>
|
|
36
|
-
>>> #
|
|
37
|
-
>>>
|
|
36
|
+
>>> # Step 2: Create DataModule
|
|
37
|
+
>>> dm = DFMDataModule(config_path='config/default.yaml', data=df_processed)
|
|
38
|
+
>>> dm.setup()
|
|
38
39
|
>>>
|
|
39
|
-
>>> # Create
|
|
40
|
-
>>>
|
|
41
|
-
>>>
|
|
40
|
+
>>> # Step 3: Create model and load config
|
|
41
|
+
>>> model = DFM()
|
|
42
|
+
>>> model.load_config('config/default.yaml')
|
|
42
43
|
>>>
|
|
43
|
-
>>> #
|
|
44
|
-
>>>
|
|
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
|
|
45
49
|
>>> Xf, Zf = model.predict(horizon=6)
|
|
46
50
|
>>>
|
|
47
|
-
>>> # Or use DDFM (
|
|
48
|
-
>>>
|
|
49
|
-
>>> ddfm_model.load_config('config/default.yaml')
|
|
51
|
+
>>> # Or use DDFM (same pattern)
|
|
52
|
+
>>> from dfm_python import DDFM, DDFMTrainer
|
|
50
53
|
>>>
|
|
51
|
-
>>>
|
|
52
|
-
>>>
|
|
53
|
-
>>> data_module_ddfm.setup()
|
|
54
|
+
>>> dm_ddfm = DFMDataModule(config_path='config/default.yaml', data=df_processed)
|
|
55
|
+
>>> dm_ddfm.setup()
|
|
54
56
|
>>>
|
|
55
|
-
>>>
|
|
56
|
-
>>> ddfm_model.
|
|
57
|
+
>>> ddfm_model = DDFM(encoder_layers=[64, 32], num_factors=2)
|
|
58
|
+
>>> ddfm_model.load_config('config/default.yaml')
|
|
59
|
+
>>>
|
|
60
|
+
>>> trainer_ddfm = DDFMTrainer(max_epochs=100)
|
|
61
|
+
>>> trainer_ddfm.fit(ddfm_model, dm_ddfm)
|
|
57
62
|
>>> Xf, Zf = ddfm_model.predict(horizon=6)
|
|
58
63
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
>>> from dfm_python.transformations.utils import read_data # Preferred import
|
|
62
|
-
>>> # Option 1: Load from YAML
|
|
63
|
-
>>> config = load_config('config.yaml')
|
|
64
|
-
>>> # Option 2: Create directly
|
|
65
|
-
>>> config = DFMConfig(
|
|
66
|
-
... series=[SeriesConfig(frequency='m', transformation='lin', blocks=[1], series_id='series1')],
|
|
67
|
-
... block_names=['Global']
|
|
68
|
-
... )
|
|
69
|
-
>>> from dfm_python.lightning import DFMDataModule
|
|
70
|
-
>>> from sktime.transformations.compose import ColumnTransformer
|
|
71
|
-
>>>
|
|
72
|
-
>>> # Create transformer (user must provide)
|
|
73
|
-
>>> transformer = ColumnTransformer([...]) # User-defined
|
|
74
|
-
>>>
|
|
75
|
-
>>> # Create DataModule
|
|
76
|
-
>>> data_module = DFMDataModule(config=config, transformer=transformer, data_path='data.csv')
|
|
77
|
-
>>> data_module.setup()
|
|
78
|
-
>>>
|
|
79
|
-
>>> # Fit model
|
|
80
|
-
>>> model = DFM()
|
|
81
|
-
>>> result = model.fit(data_module, config)
|
|
82
|
-
>>> factors = result.Z # Extract estimated factors
|
|
64
|
+
Note: DFMConfig and SeriesConfig are internal implementation details.
|
|
65
|
+
Users should use Hydra YAML configuration files instead.
|
|
83
66
|
|
|
84
67
|
For detailed documentation, see the README.md file and the tutorial notebooks/scripts.
|
|
85
68
|
"""
|
|
86
69
|
|
|
87
|
-
__version__ = "0.4.
|
|
70
|
+
__version__ = "0.4.2"
|
|
88
71
|
|
|
89
72
|
# ============================================================================
|
|
90
73
|
# PUBLIC API DEFINITION
|
|
@@ -94,23 +77,24 @@ __version__ = "0.4.0"
|
|
|
94
77
|
# Internal reorganization should not break these imports.
|
|
95
78
|
#
|
|
96
79
|
# Public API categories:
|
|
97
|
-
# 1. Configuration: DFMConfig, SeriesConfig,
|
|
80
|
+
# 1. Configuration: DFMConfig, SeriesConfig, config sources
|
|
98
81
|
# 2. High-level API: DFM, DDFM, module-level convenience functions
|
|
99
|
-
# 3. Core utilities:
|
|
82
|
+
# 3. Core utilities: DFMLinear, TimeIndex, diagnostics
|
|
100
83
|
# 4. Models: BaseFactorModel, DFMLinear, DDFM (low-level)
|
|
101
84
|
# 5. Nowcasting: Nowcast, result classes, para_const
|
|
102
|
-
# 6. Data & Results: DFMResult
|
|
85
|
+
# 6. Data & Results: DFMResult
|
|
103
86
|
# ============================================================================
|
|
104
87
|
|
|
105
88
|
# Configuration (from config/ subpackage)
|
|
106
89
|
from .config import (
|
|
107
|
-
|
|
90
|
+
DEFAULT_BLOCK_NAME,
|
|
108
91
|
ConfigSource, YamlSource, DictSource, HydraSource,
|
|
109
92
|
MergedConfigSource, make_config_source,
|
|
110
93
|
)
|
|
94
|
+
# Internal imports (for backward compatibility, but not recommended)
|
|
95
|
+
from .config import DFMConfig, SeriesConfig # Internal use only
|
|
111
96
|
|
|
112
97
|
# Data utilities
|
|
113
|
-
# Note: transform_data and DFMScaler have been removed - users must provide their own sktime transformers to DFMDataModule
|
|
114
98
|
|
|
115
99
|
# Results
|
|
116
100
|
from .config.results import DFMResult, DDFMResult, BaseResult
|
|
@@ -118,27 +102,15 @@ from .config.results import DFMResult, DDFMResult, BaseResult
|
|
|
118
102
|
# Utilities (from utils/ subpackage)
|
|
119
103
|
from .utils.diagnostics import diagnose_series, print_series_diagnosis
|
|
120
104
|
from .utils.time import calculate_rmse
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
DFMDataModule,
|
|
131
|
-
KalmanFilter, # New module class
|
|
132
|
-
EMAlgorithm, # New module class
|
|
133
|
-
)
|
|
134
|
-
_has_lightning = True
|
|
135
|
-
except ImportError:
|
|
136
|
-
_has_lightning = False
|
|
137
|
-
DFMLightningModule = None # type: ignore
|
|
138
|
-
DDFMLightningModule = None # type: ignore
|
|
139
|
-
DFMDataModule = None # type: ignore
|
|
140
|
-
KalmanFilter = None # type: ignore
|
|
141
|
-
EMAlgorithm = None # type: ignore
|
|
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
|
+
)
|
|
142
114
|
|
|
143
115
|
# Nowcasting (from nowcast/ subpackage)
|
|
144
116
|
from .nowcast import (
|
|
@@ -154,83 +126,47 @@ from .nowcast.helpers import (
|
|
|
154
126
|
# Model implementations
|
|
155
127
|
from .models.base import BaseFactorModel
|
|
156
128
|
from .models.dfm import DFMLinear, DFM
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
)
|
|
161
|
-
# Note: load_data has been removed - use DFMDataModule instead
|
|
162
|
-
|
|
163
|
-
# DDFM high-level API and low-level model (both optional, requires PyTorch)
|
|
164
|
-
try:
|
|
165
|
-
from .models.ddfm import DDFM, DDFMModel
|
|
166
|
-
from .models.ddfm import load_config_ddfm, load_data_ddfm, train_ddfm, predict_ddfm, plot_ddfm, reset_ddfm
|
|
167
|
-
_has_ddfm = True
|
|
168
|
-
except ImportError:
|
|
169
|
-
_has_ddfm = False
|
|
170
|
-
DDFM = None # type: ignore
|
|
171
|
-
DDFMModel = None # type: ignore
|
|
172
|
-
load_config_ddfm = None # type: ignore
|
|
173
|
-
load_data_ddfm = None # type: ignore
|
|
174
|
-
train_ddfm = None # type: ignore
|
|
175
|
-
predict_ddfm = None # type: ignore
|
|
176
|
-
plot_ddfm = None # type: ignore
|
|
177
|
-
reset_ddfm = None # type: ignore
|
|
178
|
-
# DDFM module-level functions removed - create DDFM() instance directly
|
|
129
|
+
|
|
130
|
+
# DDFM high-level API and low-level model (PyTorch is mandatory)
|
|
131
|
+
from .models.ddfm import DDFM, DDFMModel
|
|
179
132
|
|
|
180
133
|
__all__ = [
|
|
181
134
|
# Core classes
|
|
182
|
-
'
|
|
135
|
+
'DFM', 'DFMLinear', 'Nowcast',
|
|
183
136
|
# Model base and implementations
|
|
184
|
-
'BaseFactorModel',
|
|
137
|
+
'BaseFactorModel',
|
|
185
138
|
# Nowcast result classes
|
|
186
139
|
'NowcastResult', 'NewsDecompResult', 'BacktestResult',
|
|
187
140
|
# Constants
|
|
188
|
-
'
|
|
141
|
+
'DEFAULT_BLOCK_NAME',
|
|
189
142
|
# Config sources
|
|
190
143
|
'ConfigSource', 'YamlSource', 'DictSource', 'HydraSource',
|
|
191
144
|
'MergedConfigSource', 'make_config_source',
|
|
192
|
-
# High-level API (module-level - recommended)
|
|
193
|
-
'load_config',
|
|
194
|
-
'load_pickle', 'train', 'predict', 'plot', 'reset', 'create_model',
|
|
195
|
-
# Convenience constructors (cleaner API)
|
|
196
|
-
'from_yaml', 'from_spec', 'from_spec_df', 'from_dict',
|
|
197
145
|
# Low-level API (functional interface - advanced usage)
|
|
198
146
|
'BaseResult', 'DFMResult', 'DDFMResult', 'calculate_rmse', 'diagnose_series', 'print_series_diagnosis',
|
|
199
147
|
'para_const', # Internal utility for nowcasting
|
|
200
148
|
]
|
|
201
149
|
|
|
202
|
-
#
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
#
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
from .trainer import DFMTrainer, DDFMTrainer
|
|
225
|
-
_has_trainers = True
|
|
226
|
-
except ImportError:
|
|
227
|
-
_has_trainers = False
|
|
228
|
-
DFMTrainer = None # type: ignore
|
|
229
|
-
DDFMTrainer = None # type: ignore
|
|
230
|
-
|
|
231
|
-
if _has_trainers:
|
|
232
|
-
__all__.extend([
|
|
233
|
-
'DFMTrainer',
|
|
234
|
-
'DDFMTrainer',
|
|
235
|
-
])
|
|
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
|
+
|
|
236
172
|
|
dfm_python/config/__init__.py
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
"""Configuration subpackage for DFM.
|
|
2
2
|
|
|
3
3
|
This subpackage provides:
|
|
4
|
-
- Schema (DFMConfig, SeriesConfig
|
|
5
|
-
- IO (ConfigSource, YamlSource, etc.) in
|
|
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
|
-
BaseModelConfig, DFMConfig, DDFMConfig, SeriesConfig,
|
|
10
|
-
|
|
9
|
+
BaseModelConfig, DFMConfig, DDFMConfig, SeriesConfig,
|
|
10
|
+
DEFAULT_BLOCK_NAME,
|
|
11
11
|
)
|
|
12
|
-
from .
|
|
13
|
-
from .results import BaseResult, DFMResult, DDFMResult, DFMParams
|
|
12
|
+
from .results import BaseResult, DFMResult, DDFMResult, FitParams
|
|
14
13
|
from .utils import validate_frequency, validate_transformation
|
|
15
|
-
from .
|
|
14
|
+
from .adapter import (
|
|
16
15
|
ConfigSource,
|
|
17
16
|
YamlSource,
|
|
18
17
|
DictSource,
|
|
19
18
|
HydraSource,
|
|
20
19
|
MergedConfigSource,
|
|
21
20
|
make_config_source,
|
|
22
|
-
from_spec,
|
|
21
|
+
# Note: from_spec is in models/dfm.py, not in adapter
|
|
23
22
|
# Note: Private functions (_load_config_from_dataframe, _write_series_blocks_yaml)
|
|
24
|
-
# are available from
|
|
23
|
+
# are available from adapter module but not exported as public API
|
|
25
24
|
)
|
|
26
|
-
from .
|
|
25
|
+
from .utils import (
|
|
27
26
|
FREQUENCY_HIERARCHY,
|
|
28
27
|
PERIODS_PER_YEAR,
|
|
29
28
|
get_periods_per_year,
|
|
29
|
+
get_annual_factor,
|
|
30
30
|
compute_idio_chain_lengths,
|
|
31
31
|
get_tent_weights_for_pair,
|
|
32
32
|
generate_tent_weights,
|
|
@@ -37,22 +37,22 @@ from .structure import (
|
|
|
37
37
|
|
|
38
38
|
__all__ = [
|
|
39
39
|
# Schema
|
|
40
|
-
'BaseModelConfig', 'DFMConfig', 'DDFMConfig', 'SeriesConfig',
|
|
41
|
-
'
|
|
42
|
-
#
|
|
43
|
-
'
|
|
40
|
+
'BaseModelConfig', 'DFMConfig', 'DDFMConfig', 'SeriesConfig',
|
|
41
|
+
'DEFAULT_BLOCK_NAME',
|
|
42
|
+
# Parameter overrides
|
|
43
|
+
'FitParams',
|
|
44
44
|
# Results
|
|
45
|
-
'BaseResult', 'DFMResult', 'DDFMResult',
|
|
45
|
+
'BaseResult', 'DFMResult', 'DDFMResult',
|
|
46
46
|
# Utilities
|
|
47
47
|
'validate_frequency', 'validate_transformation',
|
|
48
48
|
# IO
|
|
49
49
|
'ConfigSource', 'YamlSource', 'DictSource',
|
|
50
50
|
'HydraSource', 'MergedConfigSource', 'make_config_source',
|
|
51
|
-
|
|
52
|
-
# Structure utilities
|
|
51
|
+
# Frequency and aggregation utilities
|
|
53
52
|
'FREQUENCY_HIERARCHY',
|
|
54
53
|
'PERIODS_PER_YEAR',
|
|
55
54
|
'get_periods_per_year',
|
|
55
|
+
'get_annual_factor',
|
|
56
56
|
'compute_idio_chain_lengths',
|
|
57
57
|
'get_tent_weights_for_pair',
|
|
58
58
|
'generate_tent_weights',
|
|
@@ -60,6 +60,6 @@ __all__ = [
|
|
|
60
60
|
'get_aggregation_structure',
|
|
61
61
|
'group_series_by_frequency',
|
|
62
62
|
# Note: Private functions (_load_config_from_dataframe, _write_series_blocks_yaml)
|
|
63
|
-
# are available from
|
|
63
|
+
# are available from adapter module but not exported as public API
|
|
64
64
|
]
|
|
65
65
|
|