deep-inference 0.1.0__tar.gz
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.
- deep_inference-0.1.0/LICENSE +21 -0
- deep_inference-0.1.0/MANIFEST.in +25 -0
- deep_inference-0.1.0/PKG-INFO +209 -0
- deep_inference-0.1.0/README.md +157 -0
- deep_inference-0.1.0/pyproject.toml +139 -0
- deep_inference-0.1.0/setup.cfg +4 -0
- deep_inference-0.1.0/src/deep_inference/__init__.py +46 -0
- deep_inference-0.1.0/src/deep_inference/classical.py +189 -0
- deep_inference-0.1.0/src/deep_inference/dgp.py +674 -0
- deep_inference-0.1.0/src/deep_inference/families.py +1094 -0
- deep_inference-0.1.0/src/deep_inference/inference.py +1048 -0
- deep_inference-0.1.0/src/deep_inference/logging.py +334 -0
- deep_inference-0.1.0/src/deep_inference/metrics.py +604 -0
- deep_inference-0.1.0/src/deep_inference/models.py +459 -0
- deep_inference-0.1.0/src/deep_inference/py.typed +0 -0
- deep_inference-0.1.0/src/deep_inference/real_data.py +269 -0
- deep_inference-0.1.0/src/deep_inference/run_mc.py +606 -0
- deep_inference-0.1.0/src/deep_inference/run_real.py +326 -0
- deep_inference-0.1.0/src/deep_inference.egg-info/PKG-INFO +209 -0
- deep_inference-0.1.0/src/deep_inference.egg-info/SOURCES.txt +21 -0
- deep_inference-0.1.0/src/deep_inference.egg-info/dependency_links.txt +1 -0
- deep_inference-0.1.0/src/deep_inference.egg-info/requires.txt +32 -0
- deep_inference-0.1.0/src/deep_inference.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Pranjal Rawat
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Include
|
|
2
|
+
include LICENSE
|
|
3
|
+
include README.md
|
|
4
|
+
include pyproject.toml
|
|
5
|
+
|
|
6
|
+
# Include source
|
|
7
|
+
recursive-include src *.py *.typed
|
|
8
|
+
|
|
9
|
+
# Exclude everything else
|
|
10
|
+
prune archive
|
|
11
|
+
prune data
|
|
12
|
+
prune docs
|
|
13
|
+
prune logs
|
|
14
|
+
prune paper
|
|
15
|
+
prune prototypes
|
|
16
|
+
prune references
|
|
17
|
+
prune tests
|
|
18
|
+
prune src2
|
|
19
|
+
global-exclude *.csv
|
|
20
|
+
global-exclude *.pkl
|
|
21
|
+
global-exclude *.json
|
|
22
|
+
global-exclude *.log
|
|
23
|
+
global-exclude __pycache__
|
|
24
|
+
global-exclude *.pyc
|
|
25
|
+
global-exclude .DS_Store
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: deep-inference
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Production-grade econometrics with neural networks
|
|
5
|
+
Author: Pranjal Rawat
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/rawatpranjal/deep-inference
|
|
8
|
+
Project-URL: Repository, https://github.com/rawatpranjal/deep-inference
|
|
9
|
+
Project-URL: Documentation, https://rawatpranjal.github.io/deep-inference
|
|
10
|
+
Keywords: econometrics,causal-inference,deep-learning,neural-networks,statistics,machine-learning
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: torch>=2.0
|
|
25
|
+
Requires-Dist: numpy>=1.24
|
|
26
|
+
Requires-Dist: pandas>=2.0
|
|
27
|
+
Requires-Dist: scipy>=1.10
|
|
28
|
+
Requires-Dist: scikit-learn>=1.3
|
|
29
|
+
Requires-Dist: formulaic>=1.0
|
|
30
|
+
Requires-Dist: tabulate>=0.9
|
|
31
|
+
Requires-Dist: tqdm>=4.65
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
35
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
36
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
37
|
+
Requires-Dist: pre-commit>=3.7; extra == "dev"
|
|
38
|
+
Provides-Extra: parity
|
|
39
|
+
Requires-Dist: rpy2>=3.5; extra == "parity"
|
|
40
|
+
Provides-Extra: docs
|
|
41
|
+
Requires-Dist: sphinx>=7.0; extra == "docs"
|
|
42
|
+
Requires-Dist: pydata-sphinx-theme>=0.16; extra == "docs"
|
|
43
|
+
Requires-Dist: myst-parser>=2.0; extra == "docs"
|
|
44
|
+
Requires-Dist: sphinx-autodoc-typehints>=1.25; extra == "docs"
|
|
45
|
+
Requires-Dist: sphinx-copybutton>=0.5; extra == "docs"
|
|
46
|
+
Provides-Extra: plotting
|
|
47
|
+
Requires-Dist: matplotlib>=3.8; extra == "plotting"
|
|
48
|
+
Requires-Dist: seaborn>=0.13; extra == "plotting"
|
|
49
|
+
Provides-Extra: all
|
|
50
|
+
Requires-Dist: deep-inference[dev,docs,parity,plotting]; extra == "all"
|
|
51
|
+
Dynamic: license-file
|
|
52
|
+
|
|
53
|
+
# `deep-inference`
|
|
54
|
+
|
|
55
|
+
**Deep Learning for Individual Heterogeneity**
|
|
56
|
+
|
|
57
|
+
`deep-inference` is a Python package for **enriching structural economic models** with deep learning. It implements the framework developed by Farrell, Liang, and Misra (2021, 2025) to recover rich, non-linear parameter heterogeneity ($\theta(X)$) while maintaining the interpretability and validity of structural economics.
|
|
58
|
+
|
|
59
|
+
Standard deep learning minimizes prediction error, which leads to biased parameter estimates ("The Inference Trap"). This package implements **Influence Function-based Debiasing** (a form of Double Machine Learning) to provide valid confidence intervals and p-values for economic targets.
|
|
60
|
+
1
|
|
61
|
+
[](https://www.python.org/downloads/)
|
|
62
|
+
[](https://opensource.org/licenses/MIT)
|
|
63
|
+
|
|
64
|
+
## Why `deep-inference`?
|
|
65
|
+
|
|
66
|
+
Economic structure and Machine Learning are **complements**, not substitutes.
|
|
67
|
+
* **Deep Learning** provides the capacity to learn complex, high-dimensional heterogeneity.
|
|
68
|
+
* **Structural Models** provide the constraints necessary for causal interpretation and counterfactuals.
|
|
69
|
+
|
|
70
|
+
`deep-inference` enforces the structural loss (e.g., Tobit likelihood) on the output of a neural network, ensuring that the estimated parameters $\alpha(X), \beta(X)$ respect the economic theory.
|
|
71
|
+
|
|
72
|
+
## Installation
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pip install deep-inference
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Quickstart
|
|
79
|
+
|
|
80
|
+
Estimate a linear demand model where Price Elasticity $\beta$ varies non-linearly with customer characteristics $X$.
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
import torch
|
|
84
|
+
from deep_inference import get_dgp, get_family, influence
|
|
85
|
+
|
|
86
|
+
# 1. Generate synthetic data (Linear Demand with Heterogeneity)
|
|
87
|
+
dgp = get_dgp("linear", seed=42)
|
|
88
|
+
data = dgp.generate(n=2000)
|
|
89
|
+
|
|
90
|
+
# 2. Define the Structural Family
|
|
91
|
+
# (Defines the Loss, Score, and Hessian automatically)
|
|
92
|
+
family = get_family("linear")
|
|
93
|
+
|
|
94
|
+
# 3. Run Inference
|
|
95
|
+
# The package trains the structural network, computes the influence function,
|
|
96
|
+
# and aggregates results via 10-fold cross-fitting.
|
|
97
|
+
result = influence(
|
|
98
|
+
X=data.X, T=data.T, Y=data.Y,
|
|
99
|
+
family=family,
|
|
100
|
+
config={
|
|
101
|
+
"hidden_dims": [128, 64, 32],
|
|
102
|
+
"epochs": 50,
|
|
103
|
+
"lr": 0.01
|
|
104
|
+
}
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
print(f"Avg Elasticity (Truth): {data.mu_true:.4f}")
|
|
108
|
+
print(f"Avg Elasticity (Est): {result.mu_hat:.4f}")
|
|
109
|
+
print(f"Standard Error: {result.se:.4f}")
|
|
110
|
+
print(f"95% CI: [{result.ci_lower:.4f}, {result.ci_upper:.4f}]")
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Supported Structural Families
|
|
114
|
+
|
|
115
|
+
The package abstracts the math of influence functions. You simply select the family that matches your outcome variable.
|
|
116
|
+
|
|
117
|
+
| Family | Model Structure | Use Case |
|
|
118
|
+
|--------|-----------------|----------|
|
|
119
|
+
| **Linear** | $Y = \alpha(X) + \beta(X)T + \varepsilon$ | Wages, Test Scores, consumption |
|
|
120
|
+
| **Logit** | $P(Y=1) = \sigma(\alpha(X) + \beta(X)T)$ | Binary Choice, Market Entry |
|
|
121
|
+
| **Tobit** | $Y = \max(0, \alpha(X) + \beta(X)T + \varepsilon)$ | Labor Supply, Censored Demand |
|
|
122
|
+
| **Poisson** | $Y \sim \text{Pois}(\exp(\alpha(X) + \beta(X)T))$ | Patent Counts, Doctor Visits |
|
|
123
|
+
| **Gamma** | $Y \sim \text{Gamma}(k(X), \theta(X))$ | Healthcare Costs, Insurance Claims |
|
|
124
|
+
| **Weibull** | $Y \sim \text{Weibull}(\dots)$ | Duration Analysis, Unemployment Spells |
|
|
125
|
+
|
|
126
|
+
*Note: For complex models like Tobit, `deep-inference` automatically handles the joint estimation of structural variance $\sigma(X)$ required for consistent inference.*
|
|
127
|
+
|
|
128
|
+
## Methodological Details
|
|
129
|
+
|
|
130
|
+
### 1. The Enriched Model
|
|
131
|
+
We replace fixed parameters $\theta$ with neural networks $\theta(X)$:
|
|
132
|
+
|
|
133
|
+
```math
|
|
134
|
+
\hat{\theta}(\cdot) = \arg \min_{\theta \in \mathcal{F}_{DNN}} \sum \ell(y_i, t_i, \theta(x_i))
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### 2. The Influence Function Correction
|
|
138
|
+
Naive averaging of $\hat{\theta}(X)$ yields biased inference. We construct a Neyman-Orthogonal score $\psi$ using the **Influence Function**:
|
|
139
|
+
|
|
140
|
+
```math
|
|
141
|
+
\psi(z) = H(\hat{\theta}) + \nabla_\theta H \cdot \Lambda(x)^{-1} \cdot \nabla_\theta \ell(z, \hat{\theta})
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Where $\Lambda(x) = \mathbb{E}[\nabla^2 \ell \mid X=x]$ is the conditional Hessian.
|
|
145
|
+
* **Automatic Differentiation:** `deep-inference` uses PyTorch Autograd to compute exact Jacobians and Hessians for any model family.
|
|
146
|
+
* **Stability:** Includes Tikhonov regularization for inverting Hessians in non-linear models (e.g., Logit/Tobit).
|
|
147
|
+
|
|
148
|
+
## Validation (Monte Carlo Results)
|
|
149
|
+
|
|
150
|
+
M=30 simulations, N=10,000 observations. Target: 95% coverage, SE ratio ≈ 1.0.
|
|
151
|
+
|
|
152
|
+
### Linear Model
|
|
153
|
+
|
|
154
|
+

|
|
155
|
+
|
|
156
|
+
| Config | K | Network | Coverage | SE Ratio | RMSE | Bias²/MSE |
|
|
157
|
+
|--------|---|---------|----------|----------|------|-----------|
|
|
158
|
+
| **Best** | 50 | [64,32] | **93.3%** | 1.03 | **0.032** | 22% |
|
|
159
|
+
| Deep | 20 | [128,64,32] | 93.3% | 1.02 | 0.033 | 21% |
|
|
160
|
+
| E=100 | 20 | [64,32] | 90.0% | 0.90 | 0.036 | 18% |
|
|
161
|
+
| Separate | 20 | [128,64,32]×2 | 80.0% | 0.82 | 0.036 | 14% |
|
|
162
|
+
| Naive | — | — | 10% | 0.09 | 0.083 | 1% |
|
|
163
|
+
|
|
164
|
+
**Finding:** K=50 folds achieves best coverage and lowest RMSE. Separate networks don't help.
|
|
165
|
+
|
|
166
|
+
### Logit Model
|
|
167
|
+
|
|
168
|
+

|
|
169
|
+
|
|
170
|
+
Target: E[β(X)] = average log-odds ratio
|
|
171
|
+
|
|
172
|
+
| Method | Coverage | SE Ratio | RMSE | Hessian min λ |
|
|
173
|
+
|--------|----------|----------|------|---------------|
|
|
174
|
+
| **Influence** | **90.0%** | 0.93 | **0.054** | 0.051 |
|
|
175
|
+
| Naive | 3.3% | 0.03 | 0.108 | — |
|
|
176
|
+
|
|
177
|
+
### Summary
|
|
178
|
+
|
|
179
|
+
| Model | Target | Naive Cov | IF Cov | RMSE Improvement |
|
|
180
|
+
|-------|--------|-----------|--------|------------------|
|
|
181
|
+
| Linear | E[β(X)] | 10% | **93%** | 2.6× |
|
|
182
|
+
| Logit | E[β(X)] | 3% | **90%** | 2.0× |
|
|
183
|
+
| Poisson | E[β(X)] | TBD | TBD | — |
|
|
184
|
+
| Gamma | E[β(X)] | TBD | TBD | — |
|
|
185
|
+
|
|
186
|
+
## Citation
|
|
187
|
+
|
|
188
|
+
```bibtex
|
|
189
|
+
@article{farrell2021deep,
|
|
190
|
+
title={Deep Neural Networks for Estimation and Inference},
|
|
191
|
+
author={Farrell, Max H. and Liang, Tengyuan and Misra, Sanjog},
|
|
192
|
+
journal={Econometrica},
|
|
193
|
+
volume={89},
|
|
194
|
+
number={1},
|
|
195
|
+
pages={181--213},
|
|
196
|
+
year={2021}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@article{farrell2025heterogeneity,
|
|
200
|
+
title={Deep Learning for Individual Heterogeneity},
|
|
201
|
+
author={Farrell, Max H. and Liang, Tengyuan and Misra, Sanjog},
|
|
202
|
+
journal={Working Paper},
|
|
203
|
+
year={2025}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## License
|
|
208
|
+
|
|
209
|
+
MIT
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# `deep-inference`
|
|
2
|
+
|
|
3
|
+
**Deep Learning for Individual Heterogeneity**
|
|
4
|
+
|
|
5
|
+
`deep-inference` is a Python package for **enriching structural economic models** with deep learning. It implements the framework developed by Farrell, Liang, and Misra (2021, 2025) to recover rich, non-linear parameter heterogeneity ($\theta(X)$) while maintaining the interpretability and validity of structural economics.
|
|
6
|
+
|
|
7
|
+
Standard deep learning minimizes prediction error, which leads to biased parameter estimates ("The Inference Trap"). This package implements **Influence Function-based Debiasing** (a form of Double Machine Learning) to provide valid confidence intervals and p-values for economic targets.
|
|
8
|
+
1
|
|
9
|
+
[](https://www.python.org/downloads/)
|
|
10
|
+
[](https://opensource.org/licenses/MIT)
|
|
11
|
+
|
|
12
|
+
## Why `deep-inference`?
|
|
13
|
+
|
|
14
|
+
Economic structure and Machine Learning are **complements**, not substitutes.
|
|
15
|
+
* **Deep Learning** provides the capacity to learn complex, high-dimensional heterogeneity.
|
|
16
|
+
* **Structural Models** provide the constraints necessary for causal interpretation and counterfactuals.
|
|
17
|
+
|
|
18
|
+
`deep-inference` enforces the structural loss (e.g., Tobit likelihood) on the output of a neural network, ensuring that the estimated parameters $\alpha(X), \beta(X)$ respect the economic theory.
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install deep-inference
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quickstart
|
|
27
|
+
|
|
28
|
+
Estimate a linear demand model where Price Elasticity $\beta$ varies non-linearly with customer characteristics $X$.
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
import torch
|
|
32
|
+
from deep_inference import get_dgp, get_family, influence
|
|
33
|
+
|
|
34
|
+
# 1. Generate synthetic data (Linear Demand with Heterogeneity)
|
|
35
|
+
dgp = get_dgp("linear", seed=42)
|
|
36
|
+
data = dgp.generate(n=2000)
|
|
37
|
+
|
|
38
|
+
# 2. Define the Structural Family
|
|
39
|
+
# (Defines the Loss, Score, and Hessian automatically)
|
|
40
|
+
family = get_family("linear")
|
|
41
|
+
|
|
42
|
+
# 3. Run Inference
|
|
43
|
+
# The package trains the structural network, computes the influence function,
|
|
44
|
+
# and aggregates results via 10-fold cross-fitting.
|
|
45
|
+
result = influence(
|
|
46
|
+
X=data.X, T=data.T, Y=data.Y,
|
|
47
|
+
family=family,
|
|
48
|
+
config={
|
|
49
|
+
"hidden_dims": [128, 64, 32],
|
|
50
|
+
"epochs": 50,
|
|
51
|
+
"lr": 0.01
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
print(f"Avg Elasticity (Truth): {data.mu_true:.4f}")
|
|
56
|
+
print(f"Avg Elasticity (Est): {result.mu_hat:.4f}")
|
|
57
|
+
print(f"Standard Error: {result.se:.4f}")
|
|
58
|
+
print(f"95% CI: [{result.ci_lower:.4f}, {result.ci_upper:.4f}]")
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Supported Structural Families
|
|
62
|
+
|
|
63
|
+
The package abstracts the math of influence functions. You simply select the family that matches your outcome variable.
|
|
64
|
+
|
|
65
|
+
| Family | Model Structure | Use Case |
|
|
66
|
+
|--------|-----------------|----------|
|
|
67
|
+
| **Linear** | $Y = \alpha(X) + \beta(X)T + \varepsilon$ | Wages, Test Scores, consumption |
|
|
68
|
+
| **Logit** | $P(Y=1) = \sigma(\alpha(X) + \beta(X)T)$ | Binary Choice, Market Entry |
|
|
69
|
+
| **Tobit** | $Y = \max(0, \alpha(X) + \beta(X)T + \varepsilon)$ | Labor Supply, Censored Demand |
|
|
70
|
+
| **Poisson** | $Y \sim \text{Pois}(\exp(\alpha(X) + \beta(X)T))$ | Patent Counts, Doctor Visits |
|
|
71
|
+
| **Gamma** | $Y \sim \text{Gamma}(k(X), \theta(X))$ | Healthcare Costs, Insurance Claims |
|
|
72
|
+
| **Weibull** | $Y \sim \text{Weibull}(\dots)$ | Duration Analysis, Unemployment Spells |
|
|
73
|
+
|
|
74
|
+
*Note: For complex models like Tobit, `deep-inference` automatically handles the joint estimation of structural variance $\sigma(X)$ required for consistent inference.*
|
|
75
|
+
|
|
76
|
+
## Methodological Details
|
|
77
|
+
|
|
78
|
+
### 1. The Enriched Model
|
|
79
|
+
We replace fixed parameters $\theta$ with neural networks $\theta(X)$:
|
|
80
|
+
|
|
81
|
+
```math
|
|
82
|
+
\hat{\theta}(\cdot) = \arg \min_{\theta \in \mathcal{F}_{DNN}} \sum \ell(y_i, t_i, \theta(x_i))
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 2. The Influence Function Correction
|
|
86
|
+
Naive averaging of $\hat{\theta}(X)$ yields biased inference. We construct a Neyman-Orthogonal score $\psi$ using the **Influence Function**:
|
|
87
|
+
|
|
88
|
+
```math
|
|
89
|
+
\psi(z) = H(\hat{\theta}) + \nabla_\theta H \cdot \Lambda(x)^{-1} \cdot \nabla_\theta \ell(z, \hat{\theta})
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Where $\Lambda(x) = \mathbb{E}[\nabla^2 \ell \mid X=x]$ is the conditional Hessian.
|
|
93
|
+
* **Automatic Differentiation:** `deep-inference` uses PyTorch Autograd to compute exact Jacobians and Hessians for any model family.
|
|
94
|
+
* **Stability:** Includes Tikhonov regularization for inverting Hessians in non-linear models (e.g., Logit/Tobit).
|
|
95
|
+
|
|
96
|
+
## Validation (Monte Carlo Results)
|
|
97
|
+
|
|
98
|
+
M=30 simulations, N=10,000 observations. Target: 95% coverage, SE ratio ≈ 1.0.
|
|
99
|
+
|
|
100
|
+
### Linear Model
|
|
101
|
+
|
|
102
|
+

|
|
103
|
+
|
|
104
|
+
| Config | K | Network | Coverage | SE Ratio | RMSE | Bias²/MSE |
|
|
105
|
+
|--------|---|---------|----------|----------|------|-----------|
|
|
106
|
+
| **Best** | 50 | [64,32] | **93.3%** | 1.03 | **0.032** | 22% |
|
|
107
|
+
| Deep | 20 | [128,64,32] | 93.3% | 1.02 | 0.033 | 21% |
|
|
108
|
+
| E=100 | 20 | [64,32] | 90.0% | 0.90 | 0.036 | 18% |
|
|
109
|
+
| Separate | 20 | [128,64,32]×2 | 80.0% | 0.82 | 0.036 | 14% |
|
|
110
|
+
| Naive | — | — | 10% | 0.09 | 0.083 | 1% |
|
|
111
|
+
|
|
112
|
+
**Finding:** K=50 folds achieves best coverage and lowest RMSE. Separate networks don't help.
|
|
113
|
+
|
|
114
|
+
### Logit Model
|
|
115
|
+
|
|
116
|
+

|
|
117
|
+
|
|
118
|
+
Target: E[β(X)] = average log-odds ratio
|
|
119
|
+
|
|
120
|
+
| Method | Coverage | SE Ratio | RMSE | Hessian min λ |
|
|
121
|
+
|--------|----------|----------|------|---------------|
|
|
122
|
+
| **Influence** | **90.0%** | 0.93 | **0.054** | 0.051 |
|
|
123
|
+
| Naive | 3.3% | 0.03 | 0.108 | — |
|
|
124
|
+
|
|
125
|
+
### Summary
|
|
126
|
+
|
|
127
|
+
| Model | Target | Naive Cov | IF Cov | RMSE Improvement |
|
|
128
|
+
|-------|--------|-----------|--------|------------------|
|
|
129
|
+
| Linear | E[β(X)] | 10% | **93%** | 2.6× |
|
|
130
|
+
| Logit | E[β(X)] | 3% | **90%** | 2.0× |
|
|
131
|
+
| Poisson | E[β(X)] | TBD | TBD | — |
|
|
132
|
+
| Gamma | E[β(X)] | TBD | TBD | — |
|
|
133
|
+
|
|
134
|
+
## Citation
|
|
135
|
+
|
|
136
|
+
```bibtex
|
|
137
|
+
@article{farrell2021deep,
|
|
138
|
+
title={Deep Neural Networks for Estimation and Inference},
|
|
139
|
+
author={Farrell, Max H. and Liang, Tengyuan and Misra, Sanjog},
|
|
140
|
+
journal={Econometrica},
|
|
141
|
+
volume={89},
|
|
142
|
+
number={1},
|
|
143
|
+
pages={181--213},
|
|
144
|
+
year={2021}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
@article{farrell2025heterogeneity,
|
|
148
|
+
title={Deep Learning for Individual Heterogeneity},
|
|
149
|
+
author={Farrell, Max H. and Liang, Tengyuan and Misra, Sanjog},
|
|
150
|
+
journal={Working Paper},
|
|
151
|
+
year={2025}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## License
|
|
156
|
+
|
|
157
|
+
MIT
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "deep-inference"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Production-grade econometrics with neural networks"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
authors = [
|
|
12
|
+
{name = "Pranjal Rawat"}
|
|
13
|
+
]
|
|
14
|
+
requires-python = ">=3.10"
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Intended Audience :: Science/Research",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
24
|
+
"Topic :: Scientific/Engineering :: Mathematics",
|
|
25
|
+
"Typing :: Typed",
|
|
26
|
+
]
|
|
27
|
+
keywords = [
|
|
28
|
+
"econometrics",
|
|
29
|
+
"causal-inference",
|
|
30
|
+
"deep-learning",
|
|
31
|
+
"neural-networks",
|
|
32
|
+
"statistics",
|
|
33
|
+
"machine-learning",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
dependencies = [
|
|
37
|
+
"torch>=2.0",
|
|
38
|
+
"numpy>=1.24",
|
|
39
|
+
"pandas>=2.0",
|
|
40
|
+
"scipy>=1.10",
|
|
41
|
+
"scikit-learn>=1.3",
|
|
42
|
+
"formulaic>=1.0",
|
|
43
|
+
"tabulate>=0.9",
|
|
44
|
+
"tqdm>=4.65",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[project.optional-dependencies]
|
|
48
|
+
dev = [
|
|
49
|
+
"pytest>=8.0",
|
|
50
|
+
"pytest-cov>=4.0",
|
|
51
|
+
"ruff>=0.4",
|
|
52
|
+
"mypy>=1.10",
|
|
53
|
+
"pre-commit>=3.7",
|
|
54
|
+
]
|
|
55
|
+
parity = [
|
|
56
|
+
"rpy2>=3.5",
|
|
57
|
+
]
|
|
58
|
+
docs = [
|
|
59
|
+
"sphinx>=7.0",
|
|
60
|
+
"pydata-sphinx-theme>=0.16",
|
|
61
|
+
"myst-parser>=2.0",
|
|
62
|
+
"sphinx-autodoc-typehints>=1.25",
|
|
63
|
+
"sphinx-copybutton>=0.5",
|
|
64
|
+
]
|
|
65
|
+
plotting = [
|
|
66
|
+
"matplotlib>=3.8",
|
|
67
|
+
"seaborn>=0.13",
|
|
68
|
+
]
|
|
69
|
+
all = [
|
|
70
|
+
"deep-inference[dev,parity,docs,plotting]",
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
[project.urls]
|
|
74
|
+
Homepage = "https://github.com/rawatpranjal/deep-inference"
|
|
75
|
+
Repository = "https://github.com/rawatpranjal/deep-inference"
|
|
76
|
+
Documentation = "https://rawatpranjal.github.io/deep-inference"
|
|
77
|
+
|
|
78
|
+
[tool.setuptools.packages.find]
|
|
79
|
+
where = ["src"]
|
|
80
|
+
|
|
81
|
+
[tool.setuptools.package-data]
|
|
82
|
+
deep_inference = ["py.typed"]
|
|
83
|
+
|
|
84
|
+
[tool.ruff]
|
|
85
|
+
line-length = 88
|
|
86
|
+
target-version = "py310"
|
|
87
|
+
src = ["src"]
|
|
88
|
+
|
|
89
|
+
[tool.ruff.lint]
|
|
90
|
+
select = [
|
|
91
|
+
"E", # pycodestyle errors
|
|
92
|
+
"W", # pycodestyle warnings
|
|
93
|
+
"F", # Pyflakes
|
|
94
|
+
"I", # isort
|
|
95
|
+
"B", # flake8-bugbear
|
|
96
|
+
"C4", # flake8-comprehensions
|
|
97
|
+
"UP", # pyupgrade
|
|
98
|
+
"NPY", # NumPy-specific rules
|
|
99
|
+
]
|
|
100
|
+
ignore = [
|
|
101
|
+
"E501", # line too long (handled by formatter)
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
[tool.ruff.lint.isort]
|
|
105
|
+
known-first-party = ["deep_inference"]
|
|
106
|
+
|
|
107
|
+
[tool.mypy]
|
|
108
|
+
python_version = "3.10"
|
|
109
|
+
warn_return_any = true
|
|
110
|
+
warn_unused_ignores = true
|
|
111
|
+
strict = true
|
|
112
|
+
plugins = ["numpy.typing.mypy_plugin"]
|
|
113
|
+
|
|
114
|
+
[[tool.mypy.overrides]]
|
|
115
|
+
module = [
|
|
116
|
+
"torch.*",
|
|
117
|
+
"scipy.*",
|
|
118
|
+
"sklearn.*",
|
|
119
|
+
"formulaic.*",
|
|
120
|
+
"tabulate.*",
|
|
121
|
+
"tqdm.*",
|
|
122
|
+
]
|
|
123
|
+
ignore_missing_imports = true
|
|
124
|
+
|
|
125
|
+
[tool.pytest.ini_options]
|
|
126
|
+
testpaths = ["tests"]
|
|
127
|
+
python_files = ["test_*.py"]
|
|
128
|
+
addopts = "-v --tb=short"
|
|
129
|
+
|
|
130
|
+
[tool.coverage.run]
|
|
131
|
+
source = ["src/deep_inference"]
|
|
132
|
+
branch = true
|
|
133
|
+
|
|
134
|
+
[tool.coverage.report]
|
|
135
|
+
exclude_lines = [
|
|
136
|
+
"pragma: no cover",
|
|
137
|
+
"if TYPE_CHECKING:",
|
|
138
|
+
"raise NotImplementedError",
|
|
139
|
+
]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""deep_inference: Influence function validation for neural network inference.
|
|
2
|
+
|
|
3
|
+
Implements the Farrell, Liang, Misra (2021, 2025) approach for valid inference
|
|
4
|
+
with neural network estimators. NOT DML - neural nets output structural
|
|
5
|
+
parameters directly and influence functions correct for regularization bias.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
from deep_inference import get_dgp, get_family, naive, influence, bootstrap
|
|
9
|
+
|
|
10
|
+
# Generate data
|
|
11
|
+
dgp = get_dgp("linear")
|
|
12
|
+
data = dgp.generate(1000)
|
|
13
|
+
|
|
14
|
+
# Get family for loss/residual/weights
|
|
15
|
+
family = get_family("linear")
|
|
16
|
+
|
|
17
|
+
# Run inference
|
|
18
|
+
mu_hat, se = influence(data.X, data.T, data.Y, family, config)
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from .dgp import get_dgp, DGPS, verify_ground_truth
|
|
22
|
+
from .families import get_family, FAMILIES
|
|
23
|
+
from .models import StructuralNet, NuisanceNet, train_structural, train_nuisance
|
|
24
|
+
from .inference import naive, influence, bootstrap, METHODS
|
|
25
|
+
from .metrics import compute_metrics, print_table
|
|
26
|
+
from .real_data import load_dataset, DATASETS, RealDataResult
|
|
27
|
+
from .classical import classical_logit, classical_poisson, classical_ols, ClassicalResult
|
|
28
|
+
|
|
29
|
+
__all__ = [
|
|
30
|
+
# DGP
|
|
31
|
+
"get_dgp", "DGPS", "verify_ground_truth",
|
|
32
|
+
# Families
|
|
33
|
+
"get_family", "FAMILIES",
|
|
34
|
+
# Models
|
|
35
|
+
"StructuralNet", "NuisanceNet", "train_structural", "train_nuisance",
|
|
36
|
+
# Inference
|
|
37
|
+
"naive", "influence", "bootstrap", "METHODS",
|
|
38
|
+
# Metrics
|
|
39
|
+
"compute_metrics", "print_table",
|
|
40
|
+
# Real data
|
|
41
|
+
"load_dataset", "DATASETS", "RealDataResult",
|
|
42
|
+
# Classical estimators
|
|
43
|
+
"classical_logit", "classical_poisson", "classical_ols", "ClassicalResult",
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
__version__ = "2.0.0"
|