aigroup-econ-mcp 1.3.3__py3-none-any.whl → 2.0.1__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.
- .gitignore +253 -0
- PKG-INFO +732 -0
- README.md +687 -0
- __init__.py +14 -0
- aigroup_econ_mcp-2.0.1.dist-info/METADATA +732 -0
- aigroup_econ_mcp-2.0.1.dist-info/RECORD +170 -0
- aigroup_econ_mcp-2.0.1.dist-info/entry_points.txt +2 -0
- aigroup_econ_mcp-2.0.1.dist-info/licenses/LICENSE +21 -0
- cli.py +32 -0
- econometrics/README.md +18 -0
- econometrics/__init__.py +191 -0
- econometrics/advanced_methods/modern_computing_machine_learning/__init__.py +30 -0
- econometrics/advanced_methods/modern_computing_machine_learning/causal_forest.py +253 -0
- econometrics/advanced_methods/modern_computing_machine_learning/double_ml.py +268 -0
- econometrics/advanced_methods/modern_computing_machine_learning/gradient_boosting.py +249 -0
- econometrics/advanced_methods/modern_computing_machine_learning/hierarchical_clustering.py +243 -0
- econometrics/advanced_methods/modern_computing_machine_learning/kmeans_clustering.py +293 -0
- econometrics/advanced_methods/modern_computing_machine_learning/neural_network.py +264 -0
- econometrics/advanced_methods/modern_computing_machine_learning/random_forest.py +195 -0
- econometrics/advanced_methods/modern_computing_machine_learning/support_vector_machine.py +226 -0
- econometrics/advanced_methods/modern_computing_machine_learning/test_all_modules.py +329 -0
- econometrics/advanced_methods/modern_computing_machine_learning/test_report.md +107 -0
- econometrics/basic_parametric_estimation/__init__.py +31 -0
- econometrics/basic_parametric_estimation/gmm/__init__.py +13 -0
- econometrics/basic_parametric_estimation/gmm/gmm_model.py +256 -0
- econometrics/basic_parametric_estimation/mle/__init__.py +13 -0
- econometrics/basic_parametric_estimation/mle/mle_model.py +241 -0
- econometrics/basic_parametric_estimation/ols/__init__.py +13 -0
- econometrics/basic_parametric_estimation/ols/ols_model.py +141 -0
- econometrics/causal_inference/__init__.py +66 -0
- econometrics/causal_inference/causal_identification_strategy/__init__.py +104 -0
- econometrics/causal_inference/causal_identification_strategy/control_function.py +112 -0
- econometrics/causal_inference/causal_identification_strategy/difference_in_differences.py +107 -0
- econometrics/causal_inference/causal_identification_strategy/event_study.py +119 -0
- econometrics/causal_inference/causal_identification_strategy/first_difference.py +89 -0
- econometrics/causal_inference/causal_identification_strategy/fixed_effects.py +103 -0
- econometrics/causal_inference/causal_identification_strategy/hausman_test.py +69 -0
- econometrics/causal_inference/causal_identification_strategy/instrumental_variables.py +145 -0
- econometrics/causal_inference/causal_identification_strategy/mediation_analysis.py +121 -0
- econometrics/causal_inference/causal_identification_strategy/moderation_analysis.py +109 -0
- econometrics/causal_inference/causal_identification_strategy/propensity_score_matching.py +140 -0
- econometrics/causal_inference/causal_identification_strategy/random_effects.py +100 -0
- econometrics/causal_inference/causal_identification_strategy/regression_discontinuity.py +98 -0
- econometrics/causal_inference/causal_identification_strategy/synthetic_control.py +111 -0
- econometrics/causal_inference/causal_identification_strategy/triple_difference.py +86 -0
- econometrics/distribution_analysis/__init__.py +28 -0
- econometrics/distribution_analysis/oaxaca_blinder.py +184 -0
- econometrics/distribution_analysis/time_series_decomposition.py +152 -0
- econometrics/distribution_analysis/variance_decomposition.py +179 -0
- econometrics/missing_data/__init__.py +18 -0
- econometrics/missing_data/imputation_methods.py +219 -0
- econometrics/missing_data/missing_data_measurement_error/__init__.py +0 -0
- econometrics/model_specification_diagnostics_robust_inference/README.md +173 -0
- econometrics/model_specification_diagnostics_robust_inference/__init__.py +78 -0
- econometrics/model_specification_diagnostics_robust_inference/diagnostic_tests/__init__.py +20 -0
- econometrics/model_specification_diagnostics_robust_inference/diagnostic_tests/diagnostic_tests_model.py +149 -0
- econometrics/model_specification_diagnostics_robust_inference/generalized_least_squares/__init__.py +15 -0
- econometrics/model_specification_diagnostics_robust_inference/generalized_least_squares/gls_model.py +130 -0
- econometrics/model_specification_diagnostics_robust_inference/model_selection/__init__.py +18 -0
- econometrics/model_specification_diagnostics_robust_inference/model_selection/model_selection_model.py +286 -0
- econometrics/model_specification_diagnostics_robust_inference/regularization/__init__.py +15 -0
- econometrics/model_specification_diagnostics_robust_inference/regularization/regularization_model.py +177 -0
- econometrics/model_specification_diagnostics_robust_inference/robust_errors/__init__.py +15 -0
- econometrics/model_specification_diagnostics_robust_inference/robust_errors/robust_errors_model.py +122 -0
- econometrics/model_specification_diagnostics_robust_inference/simultaneous_equations/__init__.py +15 -0
- econometrics/model_specification_diagnostics_robust_inference/simultaneous_equations/simultaneous_equations_model.py +246 -0
- econometrics/model_specification_diagnostics_robust_inference/weighted_least_squares/__init__.py +15 -0
- econometrics/model_specification_diagnostics_robust_inference/weighted_least_squares/wls_model.py +127 -0
- econometrics/nonparametric/__init__.py +35 -0
- econometrics/nonparametric/gam_model.py +117 -0
- econometrics/nonparametric/kernel_regression.py +161 -0
- econometrics/nonparametric/nonparametric_semiparametric_methods/__init__.py +0 -0
- econometrics/nonparametric/quantile_regression.py +249 -0
- econometrics/nonparametric/spline_regression.py +100 -0
- econometrics/spatial_econometrics/__init__.py +68 -0
- econometrics/spatial_econometrics/geographically_weighted_regression.py +211 -0
- econometrics/spatial_econometrics/gwr_simple.py +154 -0
- econometrics/spatial_econometrics/spatial_autocorrelation.py +356 -0
- econometrics/spatial_econometrics/spatial_durbin_model.py +177 -0
- econometrics/spatial_econometrics/spatial_econometrics_new/__init__.py +0 -0
- econometrics/spatial_econometrics/spatial_regression.py +315 -0
- econometrics/spatial_econometrics/spatial_weights.py +226 -0
- econometrics/specific_data_modeling/micro_discrete_limited_data/README.md +164 -0
- econometrics/specific_data_modeling/micro_discrete_limited_data/__init__.py +40 -0
- econometrics/specific_data_modeling/micro_discrete_limited_data/count_data_models.py +311 -0
- econometrics/specific_data_modeling/micro_discrete_limited_data/discrete_choice_models.py +294 -0
- econometrics/specific_data_modeling/micro_discrete_limited_data/limited_dependent_variable_models.py +282 -0
- econometrics/specific_data_modeling/survival_duration_data/__init__.py +0 -0
- econometrics/specific_data_modeling/time_series_panel_data/__init__.py +143 -0
- econometrics/specific_data_modeling/time_series_panel_data/arima_model.py +104 -0
- econometrics/specific_data_modeling/time_series_panel_data/cointegration_vecm.py +334 -0
- econometrics/specific_data_modeling/time_series_panel_data/dynamic_panel_models.py +653 -0
- econometrics/specific_data_modeling/time_series_panel_data/exponential_smoothing.py +176 -0
- econometrics/specific_data_modeling/time_series_panel_data/garch_model.py +198 -0
- econometrics/specific_data_modeling/time_series_panel_data/panel_diagnostics.py +125 -0
- econometrics/specific_data_modeling/time_series_panel_data/panel_var.py +60 -0
- econometrics/specific_data_modeling/time_series_panel_data/structural_break_tests.py +87 -0
- econometrics/specific_data_modeling/time_series_panel_data/time_varying_parameter_models.py +106 -0
- econometrics/specific_data_modeling/time_series_panel_data/unit_root_tests.py +204 -0
- econometrics/specific_data_modeling/time_series_panel_data/var_svar_model.py +372 -0
- econometrics/statistical_inference/__init__.py +21 -0
- econometrics/statistical_inference/bootstrap_methods.py +162 -0
- econometrics/statistical_inference/permutation_test.py +177 -0
- econometrics/statistical_inference/statistical_inference_techniques/__init__.py +0 -0
- econometrics/statistics/distribution_decomposition_methods/__init__.py +0 -0
- econometrics/survival_analysis/__init__.py +18 -0
- econometrics/survival_analysis/survival_models.py +259 -0
- econometrics/tests/basic_parametric_estimation_tests/__init__.py +3 -0
- econometrics/tests/basic_parametric_estimation_tests/test_gmm.py +128 -0
- econometrics/tests/basic_parametric_estimation_tests/test_mle.py +127 -0
- econometrics/tests/basic_parametric_estimation_tests/test_ols.py +100 -0
- econometrics/tests/causal_inference_tests/__init__.py +3 -0
- econometrics/tests/causal_inference_tests/detailed_test.py +441 -0
- econometrics/tests/causal_inference_tests/test_all_methods.py +418 -0
- econometrics/tests/causal_inference_tests/test_causal_identification_strategy.py +202 -0
- econometrics/tests/causal_inference_tests/test_difference_in_differences.py +53 -0
- econometrics/tests/causal_inference_tests/test_instrumental_variables.py +44 -0
- econometrics/tests/model_specification_diagnostics_tests/__init__.py +3 -0
- econometrics/tests/model_specification_diagnostics_tests/test_diagnostic_tests.py +86 -0
- econometrics/tests/model_specification_diagnostics_tests/test_robust_errors.py +89 -0
- econometrics/tests/specific_data_modeling_tests/__init__.py +3 -0
- econometrics/tests/specific_data_modeling_tests/test_arima.py +98 -0
- econometrics/tests/specific_data_modeling_tests/test_dynamic_panel.py +198 -0
- econometrics/tests/specific_data_modeling_tests/test_exponential_smoothing.py +105 -0
- econometrics/tests/specific_data_modeling_tests/test_garch.py +118 -0
- econometrics/tests/specific_data_modeling_tests/test_micro_discrete_limited_data.py +189 -0
- econometrics/tests/specific_data_modeling_tests/test_unit_root.py +156 -0
- econometrics/tests/specific_data_modeling_tests/test_var.py +124 -0
- econometrics//321/206/320/254/320/272/321/205/342/225/235/320/220/321/205/320/237/320/241/321/205/320/264/320/267/321/207/342/226/222/342/225/227/321/204/342/225/235/320/250/321/205/320/225/320/230/321/207/342/225/221/320/267/321/205/320/230/320/226/321/206/320/256/320/240.md +544 -0
- prompts/__init__.py +0 -0
- prompts/analysis_guides.py +43 -0
- pyproject.toml +85 -0
- resources/MCP_MASTER_GUIDE.md +422 -0
- resources/MCP_TOOLS_DATA_FORMAT_GUIDE.md +185 -0
- resources/__init__.py +0 -0
- server.py +97 -0
- tools/README.md +88 -0
- tools/__init__.py +119 -0
- tools/causal_inference_adapter.py +658 -0
- tools/data_loader.py +213 -0
- tools/decorators.py +38 -0
- tools/distribution_analysis_adapter.py +121 -0
- tools/econometrics_adapter.py +286 -0
- tools/gwr_simple_adapter.py +54 -0
- tools/machine_learning_adapter.py +567 -0
- tools/mcp_tool_groups/__init__.py +15 -0
- tools/mcp_tool_groups/basic_parametric_tools.py +173 -0
- tools/mcp_tool_groups/causal_inference_tools.py +643 -0
- tools/mcp_tool_groups/distribution_analysis_tools.py +169 -0
- tools/mcp_tool_groups/machine_learning_tools.py +422 -0
- tools/mcp_tool_groups/microecon_tools.py +325 -0
- tools/mcp_tool_groups/missing_data_tools.py +117 -0
- tools/mcp_tool_groups/model_specification_tools.py +402 -0
- tools/mcp_tool_groups/nonparametric_tools.py +225 -0
- tools/mcp_tool_groups/spatial_econometrics_tools.py +323 -0
- tools/mcp_tool_groups/statistical_inference_tools.py +131 -0
- tools/mcp_tool_groups/time_series_tools.py +494 -0
- tools/mcp_tools_registry.py +124 -0
- tools/microecon_adapter.py +412 -0
- tools/missing_data_adapter.py +73 -0
- tools/model_specification_adapter.py +369 -0
- tools/nonparametric_adapter.py +190 -0
- tools/output_formatter.py +563 -0
- tools/spatial_econometrics_adapter.py +318 -0
- tools/statistical_inference_adapter.py +90 -0
- tools/survival_analysis_adapter.py +46 -0
- tools/time_series_panel_data_adapter.py +858 -0
- tools/time_series_panel_data_tools.py +65 -0
- aigroup_econ_mcp/__init__.py +0 -19
- aigroup_econ_mcp/cli.py +0 -82
- aigroup_econ_mcp/config.py +0 -561
- aigroup_econ_mcp/server.py +0 -452
- aigroup_econ_mcp/tools/__init__.py +0 -19
- aigroup_econ_mcp/tools/base.py +0 -470
- aigroup_econ_mcp/tools/cache.py +0 -533
- aigroup_econ_mcp/tools/data_loader.py +0 -195
- aigroup_econ_mcp/tools/file_parser.py +0 -1027
- aigroup_econ_mcp/tools/machine_learning.py +0 -60
- aigroup_econ_mcp/tools/ml_ensemble.py +0 -210
- aigroup_econ_mcp/tools/ml_evaluation.py +0 -272
- aigroup_econ_mcp/tools/ml_models.py +0 -54
- aigroup_econ_mcp/tools/ml_regularization.py +0 -186
- aigroup_econ_mcp/tools/monitoring.py +0 -555
- aigroup_econ_mcp/tools/optimized_example.py +0 -229
- aigroup_econ_mcp/tools/panel_data.py +0 -619
- aigroup_econ_mcp/tools/regression.py +0 -214
- aigroup_econ_mcp/tools/statistics.py +0 -154
- aigroup_econ_mcp/tools/time_series.py +0 -698
- aigroup_econ_mcp/tools/timeout.py +0 -283
- aigroup_econ_mcp/tools/tool_descriptions.py +0 -410
- aigroup_econ_mcp/tools/tool_handlers.py +0 -1016
- aigroup_econ_mcp/tools/tool_registry.py +0 -478
- aigroup_econ_mcp/tools/validation.py +0 -482
- aigroup_econ_mcp-1.3.3.dist-info/METADATA +0 -525
- aigroup_econ_mcp-1.3.3.dist-info/RECORD +0 -30
- aigroup_econ_mcp-1.3.3.dist-info/entry_points.txt +0 -2
- /aigroup_econ_mcp-1.3.3.dist-info/licenses/LICENSE → /LICENSE +0 -0
- {aigroup_econ_mcp-1.3.3.dist-info → aigroup_econ_mcp-2.0.1.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"""
|
|
2
|
+
广义矩估计 (GMM) 模型实现
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import List, Optional
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
import numpy as np
|
|
8
|
+
from scipy import stats
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class GMMResult(BaseModel):
|
|
12
|
+
"""广义矩估计结果"""
|
|
13
|
+
coefficients: List[float] = Field(..., description="估计系数")
|
|
14
|
+
std_errors: List[float] = Field(..., description="系数标准误")
|
|
15
|
+
t_values: List[float] = Field(..., description="t统计量")
|
|
16
|
+
p_values: List[float] = Field(..., description="p值")
|
|
17
|
+
conf_int_lower: List[float] = Field(..., description="置信区间下界")
|
|
18
|
+
conf_int_upper: List[float] = Field(..., description="置信区间上界")
|
|
19
|
+
j_statistic: float = Field(..., description="J统计量")
|
|
20
|
+
j_p_value: float = Field(..., description="J统计量p值")
|
|
21
|
+
weight_matrix: List[List[float]] = Field(..., description="权重矩阵")
|
|
22
|
+
n_obs: int = Field(..., description="观测数量")
|
|
23
|
+
n_moments: int = Field(..., description="矩条件数量")
|
|
24
|
+
feature_names: List[str] = Field(..., description="特征名称")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _safe_inverse(matrix, reg_param=1e-10):
|
|
28
|
+
"""安全的矩阵求逆函数"""
|
|
29
|
+
try:
|
|
30
|
+
# 检查矩阵是否为空或非二维
|
|
31
|
+
if matrix.size == 0 or matrix.ndim != 2:
|
|
32
|
+
raise ValueError("矩阵为空或不是二维数组")
|
|
33
|
+
|
|
34
|
+
# 检查矩阵是否包含无效值
|
|
35
|
+
if np.isnan(matrix).any() or np.isinf(matrix).any():
|
|
36
|
+
raise ValueError("矩阵包含NaN或无穷大值")
|
|
37
|
+
|
|
38
|
+
# 尝试直接求逆
|
|
39
|
+
return np.linalg.inv(matrix)
|
|
40
|
+
except np.linalg.LinAlgError:
|
|
41
|
+
# 如果矩阵奇异,添加正则化项
|
|
42
|
+
try:
|
|
43
|
+
# 确保矩阵是方阵
|
|
44
|
+
if matrix.shape[0] != matrix.shape[1]:
|
|
45
|
+
raise ValueError("矩阵不是方阵,无法求逆")
|
|
46
|
+
|
|
47
|
+
# 添加正则化项
|
|
48
|
+
reg_matrix = matrix + np.eye(matrix.shape[0]) * reg_param
|
|
49
|
+
return np.linalg.inv(reg_matrix)
|
|
50
|
+
except np.linalg.LinAlgError:
|
|
51
|
+
# 如果仍然失败,使用伪逆
|
|
52
|
+
return np.linalg.pinv(matrix)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def gmm_estimation(
|
|
56
|
+
y_data: List[float],
|
|
57
|
+
x_data: List[List[float]],
|
|
58
|
+
instruments: Optional[List[List[float]]] = None,
|
|
59
|
+
feature_names: Optional[List[str]] = None,
|
|
60
|
+
constant: bool = True,
|
|
61
|
+
confidence_level: float = 0.95
|
|
62
|
+
) -> GMMResult:
|
|
63
|
+
"""
|
|
64
|
+
广义矩估计
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
y_data: 因变量数据
|
|
68
|
+
x_data: 自变量数据
|
|
69
|
+
instruments: 工具变量数据 (如果为None,则使用x_data作为工具变量,退化为OLS)
|
|
70
|
+
feature_names: 特征名称
|
|
71
|
+
constant: 是否包含常数项
|
|
72
|
+
confidence_level: 置信水平
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
GMMResult: 广义矩估计结果
|
|
76
|
+
|
|
77
|
+
Raises:
|
|
78
|
+
ValueError: 当输入数据无效时抛出异常
|
|
79
|
+
"""
|
|
80
|
+
# 输入验证
|
|
81
|
+
if not y_data or not x_data:
|
|
82
|
+
raise ValueError("因变量和自变量数据不能为空")
|
|
83
|
+
|
|
84
|
+
# 转换为numpy数组
|
|
85
|
+
y = np.array(y_data)
|
|
86
|
+
|
|
87
|
+
# 确保X是二维数组
|
|
88
|
+
if isinstance(x_data[0], (int, float)):
|
|
89
|
+
# 单个特征的情况
|
|
90
|
+
X = np.array(x_data).reshape(-1, 1)
|
|
91
|
+
else:
|
|
92
|
+
X = np.array(x_data)
|
|
93
|
+
|
|
94
|
+
# 验证数据维度一致性
|
|
95
|
+
if len(y) != X.shape[0]:
|
|
96
|
+
raise ValueError(f"因变量长度({len(y)})与自变量长度({X.shape[0]})不一致")
|
|
97
|
+
|
|
98
|
+
n, k = X.shape
|
|
99
|
+
|
|
100
|
+
# 处理工具变量
|
|
101
|
+
if instruments is None:
|
|
102
|
+
# 如果没有提供工具变量,则使用自变量作为工具变量(退化为OLS)
|
|
103
|
+
Z = X.copy()
|
|
104
|
+
else:
|
|
105
|
+
# 确保工具变量是二维数组
|
|
106
|
+
if isinstance(instruments[0], (int, float)):
|
|
107
|
+
Z = np.array(instruments).reshape(-1, 1)
|
|
108
|
+
else:
|
|
109
|
+
Z = np.array(instruments)
|
|
110
|
+
|
|
111
|
+
# 验证工具变量维度
|
|
112
|
+
if len(Z) != len(y):
|
|
113
|
+
raise ValueError(f"工具变量长度({len(Z)})与因变量长度({len(y)})不一致")
|
|
114
|
+
|
|
115
|
+
# 添加常数项
|
|
116
|
+
if constant:
|
|
117
|
+
X = np.column_stack([np.ones(n), X])
|
|
118
|
+
Z = np.column_stack([np.ones(n), Z])
|
|
119
|
+
if feature_names:
|
|
120
|
+
feature_names = ["const"] + feature_names
|
|
121
|
+
else:
|
|
122
|
+
feature_names = [f"const"] + [f"x{i}" for i in range(X.shape[1]-1)]
|
|
123
|
+
else:
|
|
124
|
+
if not feature_names:
|
|
125
|
+
feature_names = [f"x{i}" for i in range(X.shape[1])]
|
|
126
|
+
|
|
127
|
+
# 手动实现GMM估计
|
|
128
|
+
try:
|
|
129
|
+
# 初始化权重矩阵为单位矩阵
|
|
130
|
+
W = np.eye(Z.shape[1])
|
|
131
|
+
|
|
132
|
+
# 迭代估计直到收敛
|
|
133
|
+
for iteration in range(100): # 最大迭代次数
|
|
134
|
+
# 一步GMM估计
|
|
135
|
+
# X'Z W Z'X beta = X'Z W Z'y
|
|
136
|
+
XZ = X.T @ Z
|
|
137
|
+
ZY = Z.T @ y
|
|
138
|
+
|
|
139
|
+
# 更稳定的矩阵运算
|
|
140
|
+
left_side = XZ @ W @ XZ.T
|
|
141
|
+
right_side = XZ @ W @ ZY
|
|
142
|
+
|
|
143
|
+
# 解线性方程组
|
|
144
|
+
try:
|
|
145
|
+
beta = np.linalg.solve(left_side, right_side)
|
|
146
|
+
except np.linalg.LinAlgError:
|
|
147
|
+
# 如果矩阵奇异,使用伪逆
|
|
148
|
+
beta = np.linalg.pinv(left_side) @ right_side
|
|
149
|
+
|
|
150
|
+
# 计算残差
|
|
151
|
+
residuals = y - X @ beta
|
|
152
|
+
|
|
153
|
+
# 更新权重矩阵(基于残差的矩条件)
|
|
154
|
+
moments = Z * residuals.reshape(-1, 1)
|
|
155
|
+
S = moments.T @ moments / n # 协方差矩阵
|
|
156
|
+
|
|
157
|
+
# 在更新权重矩阵前进行有效性检查
|
|
158
|
+
if np.isnan(S).any() or np.isinf(S).any():
|
|
159
|
+
raise ValueError("矩条件协方差矩阵包含无效值")
|
|
160
|
+
|
|
161
|
+
# 安全地更新权重矩阵
|
|
162
|
+
W_new = _safe_inverse(S, reg_param=1e-8) # 增加正则化参数以提高稳定性
|
|
163
|
+
|
|
164
|
+
# 检查新权重矩阵的有效性
|
|
165
|
+
if np.isnan(W_new).any() or np.isinf(W_new).any():
|
|
166
|
+
raise ValueError("计算出的权重矩阵包含无效值")
|
|
167
|
+
|
|
168
|
+
# 检查收敛性
|
|
169
|
+
if np.allclose(W, W_new, rtol=1e-6, atol=1e-10):
|
|
170
|
+
W = W_new
|
|
171
|
+
break
|
|
172
|
+
W = W_new
|
|
173
|
+
|
|
174
|
+
# 计算最终的协方差矩阵和统计量
|
|
175
|
+
residuals = y - X @ beta
|
|
176
|
+
moments = Z * residuals.reshape(-1, 1)
|
|
177
|
+
S = moments.T @ moments / n
|
|
178
|
+
|
|
179
|
+
# 检查矩条件协方差矩阵
|
|
180
|
+
if np.isnan(S).any() or np.isinf(S).any() or np.linalg.norm(S) == 0:
|
|
181
|
+
raise ValueError("矩条件协方差矩阵无效")
|
|
182
|
+
|
|
183
|
+
# 计算系数协方差矩阵
|
|
184
|
+
# Var(beta) = (X'Z W Z'X)^(-1) X'Z W S W Z'X (X'Z W Z'X)^(-1)
|
|
185
|
+
XZ = X.T @ Z
|
|
186
|
+
|
|
187
|
+
# 检查XZ矩阵
|
|
188
|
+
if np.isnan(XZ).any() or np.isinf(XZ).any():
|
|
189
|
+
raise ValueError("X'Z矩阵包含无效值")
|
|
190
|
+
|
|
191
|
+
left_side = XZ @ W @ XZ.T
|
|
192
|
+
|
|
193
|
+
# 检查左侧矩阵
|
|
194
|
+
if np.isnan(left_side).any() or np.isinf(left_side).any():
|
|
195
|
+
raise ValueError("左侧矩阵(X'Z W Z'X)包含无效值")
|
|
196
|
+
|
|
197
|
+
left_side_inv = _safe_inverse(left_side, reg_param=1e-8) # 使用相同正则化参数
|
|
198
|
+
|
|
199
|
+
# 检查逆矩阵
|
|
200
|
+
if np.isnan(left_side_inv).any() or np.isinf(left_side_inv).any():
|
|
201
|
+
raise ValueError("左侧矩阵的逆包含无效值")
|
|
202
|
+
|
|
203
|
+
# 计算协方差矩阵
|
|
204
|
+
cov_intermediate = XZ @ W @ S @ W @ XZ.T
|
|
205
|
+
if np.isnan(cov_intermediate).any() or np.isinf(cov_intermediate).any():
|
|
206
|
+
raise ValueError("中间协方差计算包含无效值")
|
|
207
|
+
|
|
208
|
+
cov_beta = left_side_inv @ cov_intermediate @ left_side_inv
|
|
209
|
+
std_errors = np.sqrt(np.diag(cov_beta))
|
|
210
|
+
|
|
211
|
+
# 避免零标准误
|
|
212
|
+
std_errors = np.maximum(std_errors, 1e-12)
|
|
213
|
+
|
|
214
|
+
# 检查标准误
|
|
215
|
+
if np.isnan(std_errors).any() or np.isinf(std_errors).any():
|
|
216
|
+
raise ValueError("计算出的标准误包含无效值")
|
|
217
|
+
|
|
218
|
+
# 计算t统计量和p值
|
|
219
|
+
t_values = beta / std_errors
|
|
220
|
+
p_values = 2 * (1 - stats.t.cdf(np.abs(t_values), n - len(beta)))
|
|
221
|
+
|
|
222
|
+
# 计算置信区间
|
|
223
|
+
alpha = 1 - confidence_level
|
|
224
|
+
t_critical = stats.t.ppf(1 - alpha/2, n - len(beta))
|
|
225
|
+
conf_int_lower = beta - t_critical * std_errors
|
|
226
|
+
conf_int_upper = beta + t_critical * std_errors
|
|
227
|
+
|
|
228
|
+
# J统计量(过度识别约束检验)
|
|
229
|
+
if Z.shape[1] > len(beta):
|
|
230
|
+
# 过度识别情况
|
|
231
|
+
moment_conditions = Z.T @ residuals
|
|
232
|
+
j_statistic = n * moment_conditions.T @ W @ moment_conditions
|
|
233
|
+
j_df = Z.shape[1] - len(beta)
|
|
234
|
+
j_p_value = 1 - stats.chi2.cdf(j_statistic, j_df)
|
|
235
|
+
else:
|
|
236
|
+
# 恰好识别情况
|
|
237
|
+
j_statistic = 0.0
|
|
238
|
+
j_p_value = 1.0
|
|
239
|
+
|
|
240
|
+
return GMMResult(
|
|
241
|
+
coefficients=beta.tolist(),
|
|
242
|
+
std_errors=std_errors.tolist(),
|
|
243
|
+
t_values=t_values.tolist(),
|
|
244
|
+
p_values=p_values.tolist(),
|
|
245
|
+
conf_int_lower=conf_int_lower.tolist(),
|
|
246
|
+
conf_int_upper=conf_int_upper.tolist(),
|
|
247
|
+
j_statistic=float(j_statistic),
|
|
248
|
+
j_p_value=float(j_p_value),
|
|
249
|
+
weight_matrix=W.tolist(),
|
|
250
|
+
n_obs=n,
|
|
251
|
+
n_moments=Z.shape[1],
|
|
252
|
+
feature_names=feature_names
|
|
253
|
+
)
|
|
254
|
+
except Exception as e:
|
|
255
|
+
# 如果GMM失败,抛出异常
|
|
256
|
+
raise ValueError(f"GMM估计失败: {str(e)}")
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"""
|
|
2
|
+
最大似然估计 (MLE) 模型实现
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import List, Dict, Any, Optional, Callable
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
import numpy as np
|
|
9
|
+
import pandas as pd
|
|
10
|
+
from scipy.optimize import minimize
|
|
11
|
+
from scipy import stats
|
|
12
|
+
import statsmodels.api as sm
|
|
13
|
+
from statsmodels.base.model import GenericLikelihoodModel
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class MLEResult(BaseModel):
|
|
17
|
+
"""最大似然估计结果"""
|
|
18
|
+
parameters: List[float] = Field(..., description="估计参数")
|
|
19
|
+
std_errors: List[float] = Field(..., description="参数标准误")
|
|
20
|
+
conf_int_lower: List[float] = Field(..., description="置信区间下界")
|
|
21
|
+
conf_int_upper: List[float] = Field(..., description="置信区间上界")
|
|
22
|
+
log_likelihood: float = Field(..., description="对数似然值")
|
|
23
|
+
aic: float = Field(..., description="赤池信息准则")
|
|
24
|
+
bic: float = Field(..., description="贝叶斯信息准则")
|
|
25
|
+
convergence: bool = Field(..., description="是否收敛")
|
|
26
|
+
n_obs: int = Field(..., description="观测数量")
|
|
27
|
+
param_names: List[str] = Field(..., description="参数名称")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def mle_estimation(
|
|
31
|
+
data: List[float],
|
|
32
|
+
distribution: str = "normal",
|
|
33
|
+
initial_params: Optional[List[float]] = None,
|
|
34
|
+
confidence_level: float = 0.95
|
|
35
|
+
) -> MLEResult:
|
|
36
|
+
"""
|
|
37
|
+
最大似然估计
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
data: 数据
|
|
41
|
+
distribution: 分布类型 ('normal', 'poisson', 'exponential')
|
|
42
|
+
initial_params: 初始参数值
|
|
43
|
+
confidence_level: 置信水平
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
MLEResult: 最大似然估计结果
|
|
47
|
+
|
|
48
|
+
Raises:
|
|
49
|
+
ValueError: 当输入数据无效时抛出异常
|
|
50
|
+
"""
|
|
51
|
+
# 输入验证
|
|
52
|
+
if not data:
|
|
53
|
+
raise ValueError("数据不能为空")
|
|
54
|
+
|
|
55
|
+
data = np.array(data, dtype=np.float64)
|
|
56
|
+
n = len(data)
|
|
57
|
+
|
|
58
|
+
# 检查数据有效性
|
|
59
|
+
if np.isnan(data).any():
|
|
60
|
+
raise ValueError("数据中包含缺失值(NaN)")
|
|
61
|
+
|
|
62
|
+
if np.isinf(data).any():
|
|
63
|
+
raise ValueError("数据中包含无穷大值")
|
|
64
|
+
|
|
65
|
+
# 分布特定的验证
|
|
66
|
+
if distribution == "exponential" and np.any(data < 0):
|
|
67
|
+
raise ValueError("指数分布的数据必须为非负数")
|
|
68
|
+
|
|
69
|
+
if distribution == "poisson" and (np.any(data < 0) or not np.all(data == np.floor(data))):
|
|
70
|
+
raise ValueError("泊松分布的数据必须为非负整数")
|
|
71
|
+
|
|
72
|
+
if distribution == "normal":
|
|
73
|
+
# 正态分布的MLE
|
|
74
|
+
return _normal_mle(data, initial_params, confidence_level)
|
|
75
|
+
elif distribution == "poisson":
|
|
76
|
+
# 泊松分布的MLE
|
|
77
|
+
return _poisson_mle(data, initial_params, confidence_level)
|
|
78
|
+
elif distribution == "exponential":
|
|
79
|
+
# 指数分布的MLE
|
|
80
|
+
return _exponential_mle(data, initial_params, confidence_level)
|
|
81
|
+
else:
|
|
82
|
+
raise ValueError(f"不支持的分布类型: {distribution}")
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _normal_mle(data: np.ndarray, initial_params: Optional[List[float]], confidence_level: float) -> MLEResult:
|
|
86
|
+
"""正态分布最大似然估计"""
|
|
87
|
+
# 使用样本均值和标准差作为初始估计
|
|
88
|
+
mu_hat = np.mean(data)
|
|
89
|
+
sigma_hat = np.std(data, ddof=1) # 使用样本标准差
|
|
90
|
+
|
|
91
|
+
# 检查标准差是否为零
|
|
92
|
+
if sigma_hat == 0:
|
|
93
|
+
raise ValueError("数据标准差为零,无法进行正态分布MLE估计")
|
|
94
|
+
|
|
95
|
+
# 使用statsmodels的MLE估计
|
|
96
|
+
try:
|
|
97
|
+
# 直接使用解析解
|
|
98
|
+
n = len(data)
|
|
99
|
+
log_likelihood = float(np.sum(stats.norm.logpdf(data, loc=mu_hat, scale=sigma_hat)))
|
|
100
|
+
|
|
101
|
+
# 标准误
|
|
102
|
+
std_error_mu = sigma_hat / np.sqrt(n)
|
|
103
|
+
std_error_sigma = sigma_hat / np.sqrt(2 * n)
|
|
104
|
+
std_errors = [std_error_mu, std_error_sigma]
|
|
105
|
+
|
|
106
|
+
# 置信区间
|
|
107
|
+
alpha = 1 - confidence_level
|
|
108
|
+
z_value = stats.norm.ppf(1 - alpha/2)
|
|
109
|
+
conf_int_lower = [mu_hat - z_value * std_error_mu, sigma_hat - z_value * std_error_sigma]
|
|
110
|
+
conf_int_upper = [mu_hat + z_value * std_error_mu, sigma_hat + z_value * std_error_sigma]
|
|
111
|
+
|
|
112
|
+
# 信息准则
|
|
113
|
+
k = 2 # 参数数量
|
|
114
|
+
aic = -2 * log_likelihood + 2 * k
|
|
115
|
+
bic = -2 * log_likelihood + k * np.log(n)
|
|
116
|
+
|
|
117
|
+
return MLEResult(
|
|
118
|
+
parameters=[float(mu_hat), float(sigma_hat)],
|
|
119
|
+
std_errors=std_errors,
|
|
120
|
+
conf_int_lower=conf_int_lower,
|
|
121
|
+
conf_int_upper=conf_int_upper,
|
|
122
|
+
log_likelihood=log_likelihood,
|
|
123
|
+
aic=float(aic),
|
|
124
|
+
bic=float(bic),
|
|
125
|
+
convergence=True,
|
|
126
|
+
n_obs=n,
|
|
127
|
+
param_names=["mu", "sigma"]
|
|
128
|
+
)
|
|
129
|
+
except Exception as e:
|
|
130
|
+
raise ValueError(f"正态分布MLE估计失败: {str(e)}")
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def _poisson_mle(data: np.ndarray, initial_params: Optional[List[float]], confidence_level: float) -> MLEResult:
|
|
134
|
+
"""泊松分布最大似然估计"""
|
|
135
|
+
# 泊松分布的MLE有解析解:lambda_hat = mean(data)
|
|
136
|
+
lambda_hat = np.mean(data)
|
|
137
|
+
n = len(data)
|
|
138
|
+
|
|
139
|
+
# 检查均值是否为零
|
|
140
|
+
if lambda_hat == 0:
|
|
141
|
+
raise ValueError("数据均值为零,无法进行泊松分布MLE估计")
|
|
142
|
+
|
|
143
|
+
try:
|
|
144
|
+
# 计算对数似然值
|
|
145
|
+
log_likelihood = float(np.sum(stats.poisson.logpmf(data, lambda_hat)))
|
|
146
|
+
|
|
147
|
+
# 标准误
|
|
148
|
+
std_error = np.sqrt(lambda_hat / n)
|
|
149
|
+
std_errors = [std_error]
|
|
150
|
+
|
|
151
|
+
# 置信区间
|
|
152
|
+
alpha = 1 - confidence_level
|
|
153
|
+
z_value = stats.norm.ppf(1 - alpha/2)
|
|
154
|
+
conf_int_lower = [lambda_hat - z_value * std_error]
|
|
155
|
+
conf_int_upper = [lambda_hat + z_value * std_error]
|
|
156
|
+
|
|
157
|
+
# 信息准则
|
|
158
|
+
k = 1 # 参数数量
|
|
159
|
+
aic = -2 * log_likelihood + 2 * k
|
|
160
|
+
bic = -2 * log_likelihood + k * np.log(n)
|
|
161
|
+
|
|
162
|
+
return MLEResult(
|
|
163
|
+
parameters=[float(lambda_hat)],
|
|
164
|
+
std_errors=std_errors,
|
|
165
|
+
conf_int_lower=conf_int_lower,
|
|
166
|
+
conf_int_upper=conf_int_upper,
|
|
167
|
+
log_likelihood=log_likelihood,
|
|
168
|
+
aic=float(aic),
|
|
169
|
+
bic=float(bic),
|
|
170
|
+
convergence=True,
|
|
171
|
+
n_obs=n,
|
|
172
|
+
param_names=["lambda"]
|
|
173
|
+
)
|
|
174
|
+
except Exception as e:
|
|
175
|
+
raise ValueError(f"泊松分布MLE估计失败: {str(e)}")
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def _exponential_mle(data: np.ndarray, initial_params: Optional[List[float]], confidence_level: float) -> MLEResult:
|
|
179
|
+
"""指数分布最大似然估计"""
|
|
180
|
+
# 指数分布的MLE有解析解:lambda_hat = 1 / mean(data)
|
|
181
|
+
mean_data = np.mean(data)
|
|
182
|
+
if mean_data <= 0:
|
|
183
|
+
raise ValueError("指数分布的数据均值必须为正数")
|
|
184
|
+
|
|
185
|
+
lambda_hat = 1.0 / mean_data
|
|
186
|
+
n = len(data)
|
|
187
|
+
|
|
188
|
+
# 检查参数有效性
|
|
189
|
+
if not np.isfinite(lambda_hat):
|
|
190
|
+
raise ValueError("计算出的参数值无效")
|
|
191
|
+
|
|
192
|
+
try:
|
|
193
|
+
# 计算对数似然值
|
|
194
|
+
log_likelihood = float(np.sum(stats.expon.logpdf(data, scale=1/lambda_hat)))
|
|
195
|
+
|
|
196
|
+
# 标准误计算 (对于指数分布,标准误为lambda/sqrt(n))
|
|
197
|
+
# 使用更精确的计算方法
|
|
198
|
+
std_error = lambda_hat / np.sqrt(n)
|
|
199
|
+
std_errors = [std_error]
|
|
200
|
+
|
|
201
|
+
# 验证标准误的有效性
|
|
202
|
+
if not np.isfinite(std_error) or std_error <= 0:
|
|
203
|
+
raise ValueError("计算出的标准误无效")
|
|
204
|
+
|
|
205
|
+
# 置信区间
|
|
206
|
+
alpha = 1 - confidence_level
|
|
207
|
+
z_value = stats.norm.ppf(1 - alpha/2)
|
|
208
|
+
|
|
209
|
+
# 检查z值有效性
|
|
210
|
+
if not np.isfinite(z_value):
|
|
211
|
+
raise ValueError("计算出的临界值无效")
|
|
212
|
+
|
|
213
|
+
conf_int_lower = [lambda_hat - z_value * std_error]
|
|
214
|
+
conf_int_upper = [lambda_hat + z_value * std_error]
|
|
215
|
+
|
|
216
|
+
# 检查置信区间边界有效性
|
|
217
|
+
if not (np.isfinite(conf_int_lower[0]) and np.isfinite(conf_int_upper[0])):
|
|
218
|
+
raise ValueError("计算出的置信区间无效")
|
|
219
|
+
|
|
220
|
+
# 确保置信区间下限不为负
|
|
221
|
+
conf_int_lower[0] = max(conf_int_lower[0], 1e-10)
|
|
222
|
+
|
|
223
|
+
# 信息准则
|
|
224
|
+
k = 1 # 参数数量
|
|
225
|
+
aic = -2 * log_likelihood + 2 * k
|
|
226
|
+
bic = -2 * log_likelihood + k * np.log(n)
|
|
227
|
+
|
|
228
|
+
return MLEResult(
|
|
229
|
+
parameters=[float(lambda_hat)],
|
|
230
|
+
std_errors=std_errors,
|
|
231
|
+
conf_int_lower=conf_int_lower,
|
|
232
|
+
conf_int_upper=conf_int_upper,
|
|
233
|
+
log_likelihood=log_likelihood,
|
|
234
|
+
aic=float(aic),
|
|
235
|
+
bic=float(bic),
|
|
236
|
+
convergence=True,
|
|
237
|
+
n_obs=n,
|
|
238
|
+
param_names=["lambda"]
|
|
239
|
+
)
|
|
240
|
+
except Exception as e:
|
|
241
|
+
raise ValueError(f"指数分布MLE估计失败: {str(e)}")
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""
|
|
2
|
+
普通最小二乘法 (OLS) 模型实现
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import List, Dict, Any, Optional, Union
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
import numpy as np
|
|
9
|
+
import pandas as pd
|
|
10
|
+
from scipy import stats
|
|
11
|
+
import statsmodels.api as sm
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class OLSResult(BaseModel):
|
|
15
|
+
"""OLS回归结果"""
|
|
16
|
+
coefficients: List[float] = Field(..., description="回归系数")
|
|
17
|
+
std_errors: List[float] = Field(..., description="系数标准误")
|
|
18
|
+
t_values: List[float] = Field(..., description="t统计量")
|
|
19
|
+
p_values: List[float] = Field(..., description="p值")
|
|
20
|
+
conf_int_lower: List[float] = Field(..., description="置信区间下界")
|
|
21
|
+
conf_int_upper: List[float] = Field(..., description="置信区间上界")
|
|
22
|
+
r_squared: float = Field(..., description="R方")
|
|
23
|
+
adj_r_squared: float = Field(..., description="调整R方")
|
|
24
|
+
f_statistic: float = Field(..., description="F统计量")
|
|
25
|
+
f_p_value: float = Field(..., description="F统计量p值")
|
|
26
|
+
aic: float = Field(..., description="赤池信息准则")
|
|
27
|
+
bic: float = Field(..., description="贝叶斯信息准则")
|
|
28
|
+
n_obs: int = Field(..., description="观测数量")
|
|
29
|
+
feature_names: List[str] = Field(..., description="特征名称")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def ols_regression(
|
|
33
|
+
y_data: List[float],
|
|
34
|
+
x_data: List[List[float]],
|
|
35
|
+
feature_names: Optional[List[str]] = None,
|
|
36
|
+
constant: bool = True,
|
|
37
|
+
confidence_level: float = 0.95
|
|
38
|
+
) -> OLSResult:
|
|
39
|
+
"""
|
|
40
|
+
普通最小二乘法回归
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
y_data: 因变量数据
|
|
44
|
+
x_data: 自变量数据
|
|
45
|
+
feature_names: 特征名称
|
|
46
|
+
constant: 是否包含常数项
|
|
47
|
+
confidence_level: 置信水平
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
OLSResult: OLS回归结果
|
|
51
|
+
|
|
52
|
+
Raises:
|
|
53
|
+
ValueError: 当输入数据无效时抛出异常
|
|
54
|
+
"""
|
|
55
|
+
# 输入验证
|
|
56
|
+
if not y_data or not x_data:
|
|
57
|
+
raise ValueError("因变量和自变量数据不能为空")
|
|
58
|
+
|
|
59
|
+
# 转换为numpy数组
|
|
60
|
+
y = np.array(y_data, dtype=np.float64)
|
|
61
|
+
|
|
62
|
+
# 确保X是二维数组
|
|
63
|
+
if x_data and isinstance(x_data[0], (int, float)):
|
|
64
|
+
# 单个特征的情况,需要转置
|
|
65
|
+
X = np.array(x_data, dtype=np.float64).reshape(-1, 1)
|
|
66
|
+
else:
|
|
67
|
+
X = np.array(x_data, dtype=np.float64)
|
|
68
|
+
|
|
69
|
+
# 验证数据维度一致性
|
|
70
|
+
if len(y) != X.shape[0]:
|
|
71
|
+
raise ValueError(f"因变量长度({len(y)})与自变量长度({X.shape[0]})不一致")
|
|
72
|
+
|
|
73
|
+
# 检查是否有足够的数据点
|
|
74
|
+
if len(y) < X.shape[1] + (1 if constant else 0):
|
|
75
|
+
raise ValueError("数据点数量不足以估计模型参数")
|
|
76
|
+
|
|
77
|
+
# 检查是否存在缺失值或无穷大值
|
|
78
|
+
if np.isnan(y).any() or np.isnan(X).any():
|
|
79
|
+
raise ValueError("数据中包含缺失值(NaN)")
|
|
80
|
+
|
|
81
|
+
if np.isinf(y).any() or np.isinf(X).any():
|
|
82
|
+
raise ValueError("数据中包含无穷大值")
|
|
83
|
+
|
|
84
|
+
# 添加常数项
|
|
85
|
+
if constant:
|
|
86
|
+
X = sm.add_constant(X)
|
|
87
|
+
if feature_names:
|
|
88
|
+
feature_names = ["const"] + feature_names
|
|
89
|
+
else:
|
|
90
|
+
feature_names = ["const"] + [f"x{i}" for i in range(X.shape[1]-1)]
|
|
91
|
+
else:
|
|
92
|
+
if not feature_names:
|
|
93
|
+
feature_names = [f"x{i}" for i in range(X.shape[1])]
|
|
94
|
+
|
|
95
|
+
# 使用statsmodels执行OLS回归
|
|
96
|
+
try:
|
|
97
|
+
model = sm.OLS(y, X)
|
|
98
|
+
results = model.fit()
|
|
99
|
+
except Exception as e:
|
|
100
|
+
raise ValueError(f"无法拟合OLS模型: {str(e)}")
|
|
101
|
+
|
|
102
|
+
# 提取结果
|
|
103
|
+
coefficients = results.params.tolist()
|
|
104
|
+
std_errors = results.bse.tolist()
|
|
105
|
+
t_values = results.tvalues.tolist()
|
|
106
|
+
p_values = results.pvalues.tolist()
|
|
107
|
+
|
|
108
|
+
# 计算置信区间
|
|
109
|
+
alpha = 1 - confidence_level
|
|
110
|
+
conf_int = results.conf_int(alpha=alpha)
|
|
111
|
+
conf_int_lower = conf_int[:, 0].tolist()
|
|
112
|
+
conf_int_upper = conf_int[:, 1].tolist()
|
|
113
|
+
|
|
114
|
+
# 其他统计量
|
|
115
|
+
r_squared = float(results.rsquared)
|
|
116
|
+
adj_r_squared = float(results.rsquared_adj)
|
|
117
|
+
|
|
118
|
+
# F统计量
|
|
119
|
+
f_statistic = float(results.fvalue) if not np.isnan(results.fvalue) else 0.0
|
|
120
|
+
f_p_value = float(results.f_pvalue) if not np.isnan(results.f_pvalue) else 1.0
|
|
121
|
+
|
|
122
|
+
# 信息准则
|
|
123
|
+
aic = float(results.aic)
|
|
124
|
+
bic = float(results.bic)
|
|
125
|
+
|
|
126
|
+
return OLSResult(
|
|
127
|
+
coefficients=coefficients,
|
|
128
|
+
std_errors=std_errors,
|
|
129
|
+
t_values=t_values,
|
|
130
|
+
p_values=p_values,
|
|
131
|
+
conf_int_lower=conf_int_lower,
|
|
132
|
+
conf_int_upper=conf_int_upper,
|
|
133
|
+
r_squared=r_squared,
|
|
134
|
+
adj_r_squared=adj_r_squared,
|
|
135
|
+
f_statistic=f_statistic,
|
|
136
|
+
f_p_value=f_p_value,
|
|
137
|
+
aic=aic,
|
|
138
|
+
bic=bic,
|
|
139
|
+
n_obs=int(results.nobs),
|
|
140
|
+
feature_names=feature_names
|
|
141
|
+
)
|