aigroup-econ-mcp 0.6.0__tar.gz → 0.7.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.

Potentially problematic release.


This version of aigroup-econ-mcp might be problematic. Click here for more details.

Files changed (30) hide show
  1. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/PKG-INFO +1 -1
  2. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/pyproject.toml +1 -1
  3. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/__init__.py +1 -1
  4. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/ml_regularization.py +22 -8
  5. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/panel_data.py +70 -4
  6. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/tool_descriptions.py +55 -9
  7. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/tool_handlers.py +134 -6
  8. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/.gitignore +0 -0
  9. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/LICENSE +0 -0
  10. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/README.md +0 -0
  11. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/cli.py +0 -0
  12. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/config.py +0 -0
  13. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/server.py +0 -0
  14. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/__init__.py +0 -0
  15. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/base.py +0 -0
  16. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/cache.py +0 -0
  17. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/data_loader.py +0 -0
  18. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/file_parser.py +0 -0
  19. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/machine_learning.py +0 -0
  20. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/ml_ensemble.py +0 -0
  21. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/ml_evaluation.py +0 -0
  22. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/ml_models.py +0 -0
  23. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/monitoring.py +0 -0
  24. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/optimized_example.py +0 -0
  25. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/regression.py +0 -0
  26. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/statistics.py +0 -0
  27. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/time_series.py +0 -0
  28. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/timeout.py +0 -0
  29. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/tool_registry.py +0 -0
  30. {aigroup_econ_mcp-0.6.0 → aigroup_econ_mcp-0.7.0}/src/aigroup_econ_mcp/tools/validation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aigroup-econ-mcp
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: 专业计量经济学MCP工具 - 让大模型直接进行数据分析(优化版:增强工具描述,提升大模型调用体验)
5
5
  Project-URL: Homepage, https://github.com/aigroup/aigroup-econ-mcp
6
6
  Project-URL: Repository, https://github.com/aigroup/aigroup-econ-mcp.git
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "aigroup-econ-mcp"
7
- version = "0.6.0"
7
+ version = "0.7.0"
8
8
  description = "专业计量经济学MCP工具 - 让大模型直接进行数据分析(优化版:增强工具描述,提升大模型调用体验)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -10,7 +10,7 @@ AIGroup 计量经济学 MCP 服务
10
10
  - 模型诊断
11
11
  """
12
12
 
13
- __version__ = "0.5.0"
13
+ __version__ = "0.7.0"
14
14
  __author__ = "AIGroup"
15
15
  __description__ = "专业计量经济学MCP工具 - 让大模型直接进行数据分析(重构版:工具描述模块化)"
16
16
 
@@ -130,36 +130,50 @@ def _regularized_regression(
130
130
  elif len(feature_names) != X.shape[1]:
131
131
  raise ValueError(f"特征名称数量({len(feature_names)})与自变量数量({X.shape[1]})不匹配")
132
132
 
133
- # 数据标准化
133
+ # 检查数据质量
134
+ if len(y) < 5:
135
+ warnings.warn(f"⚠️ 警告:样本数量较少({len(y)}个),正则化回归可能不稳定")
136
+
137
+ # 数据标准化 - 只标准化自变量,不标准化因变量
134
138
  scaler = StandardScaler()
135
139
  X_scaled = scaler.fit_transform(X)
136
- y_scaled = (y - np.mean(y)) / np.std(y) # 标准化因变量
137
140
 
138
141
  # 选择模型
139
142
  if model_type == "lasso":
140
- model = Lasso(alpha=alpha, random_state=random_state, max_iter=10000)
143
+ model = Lasso(alpha=alpha, random_state=random_state, max_iter=10000, tol=1e-4)
144
+ # 对于Lasso,如果alpha过大,建议使用更小的值
145
+ if alpha > 10:
146
+ warnings.warn(f"⚠️ 警告:Lasso正则化参数alpha={alpha}可能过大,建议尝试更小的值(如0.1-1.0)")
141
147
  elif model_type == "ridge":
142
148
  model = Ridge(alpha=alpha, random_state=random_state)
143
149
  else:
144
150
  raise ValueError(f"不支持的模型类型: {model_type}")
145
151
 
146
152
  # 训练模型
147
- model.fit(X_scaled, y_scaled)
153
+ try:
154
+ model.fit(X_scaled, y)
155
+ except Exception as e:
156
+ raise ValueError(f"{model_type}模型拟合失败: {str(e)}。建议:1) 检查数据质量 2) 尝试不同的alpha值 3) 增加样本数量")
148
157
 
149
158
  # 预测
150
- y_pred_scaled = model.predict(X_scaled)
151
-
152
- # 将预测值转换回原始尺度
153
- y_pred = y_pred_scaled * np.std(y) + np.mean(y)
159
+ y_pred = model.predict(X_scaled)
154
160
 
155
161
  # 计算评估指标
156
162
  r2 = r2_score(y, y_pred)
157
163
  mse = mean_squared_error(y, y_pred)
158
164
  mae = mean_absolute_error(y, y_pred)
159
165
 
166
+ # 检查R²是否为负值
167
+ if r2 < 0:
168
+ warnings.warn(f"⚠️ 警告:{model_type}模型的R²为负值({r2:.4f}),表明模型性能比简单均值预测更差。可能原因:1) 数据噪声过大 2) 特征与目标变量无关 3) 正则化参数过大 4) 样本量过小")
169
+
160
170
  # 系数(注意:由于标准化,系数需要适当解释)
161
171
  coefficients = dict(zip(feature_names, model.coef_))
162
172
 
173
+ # 检查系数是否全为0(Lasso过度压缩)
174
+ if model_type == "lasso" and all(abs(coef) < 1e-10 for coef in model.coef_):
175
+ warnings.warn(f"⚠️ 警告:Lasso模型所有系数都被压缩为0,表明正则化参数alpha={alpha}可能过大,建议减小alpha值")
176
+
163
177
  return RegularizedRegressionResult(
164
178
  model_type=model_type,
165
179
  r2_score=r2,
@@ -63,6 +63,23 @@ def prepare_panel_data(
63
63
  """
64
64
  准备面板数据格式
65
65
 
66
+ 📊 数据格式要求:
67
+ - 因变量(y_data): 数值列表,如 [1.2, 3.4, 5.6, ...]
68
+ - 自变量(X_data): 二维数值列表,如 [[1, 2], [3, 4], [5, 6], ...]
69
+ - 实体ID(entity_ids): 字符串列表,标识不同个体,如 ['A', 'A', 'B', 'B', ...]
70
+ - 时间标识符(time_periods): 字符串或数值列表,标识时间点,如 ['2020', '2020', '2021', '2021', ...]
71
+
72
+ 💡 使用示例:
73
+ y_data = [10, 12, 8, 9] # 4个观测值
74
+ X_data = [[1, 2], [2, 3], [1, 1], [2, 2]] # 2个自变量,4个观测值
75
+ entity_ids = ['A', 'A', 'B', 'B'] # 2个实体,每个实体2个时间点
76
+ time_periods = ['2020', '2021', '2020', '2021'] # 2个时间点
77
+
78
+ ⚠️ 注意事项:
79
+ - 确保每个实体有相同的时间点数量(平衡面板)
80
+ - 实体ID和时间标识符的组合必须唯一
81
+ - 建议至少3个实体,每个实体至少2个时间点
82
+
66
83
  Args:
67
84
  y_data: 因变量数据
68
85
  X_data: 自变量数据,二维列表
@@ -73,13 +90,62 @@ def prepare_panel_data(
73
90
  Returns:
74
91
  pd.DataFrame: 面板数据格式的DataFrame
75
92
  """
76
- # 数据验证
93
+ # 数据验证 - 提供更详细的错误信息
94
+ if not y_data or not X_data or not entity_ids or not time_periods:
95
+ raise ValueError("所有输入数据都不能为空。请提供:因变量(y_data)、自变量(X_data)、实体ID(entity_ids)、时间标识符(time_periods)")
96
+
77
97
  if len(y_data) != len(X_data):
78
- raise ValueError("因变量和自变量的观测数量不一致")
98
+ raise ValueError(f"因变量和自变量的观测数量不一致:因变量有{len(y_data)}个观测值,自变量有{len(X_data)}个观测值")
99
+
79
100
  if len(y_data) != len(entity_ids):
80
- raise ValueError("因变量和个体标识符数量不一致")
101
+ raise ValueError(f"因变量和个体标识符数量不一致:因变量有{len(y_data)}个观测值,实体ID有{len(entity_ids)}个")
102
+
81
103
  if len(y_data) != len(time_periods):
82
- raise ValueError("因变量和时间标识符数量不一致")
104
+ raise ValueError(f"因变量和时间标识符数量不一致:因变量有{len(y_data)}个观测值,时间标识符有{len(time_periods)}个")
105
+
106
+ # 检查自变量维度一致性
107
+ if len(X_data) > 0:
108
+ first_dim = len(X_data[0])
109
+ for i, x_row in enumerate(X_data):
110
+ if len(x_row) != first_dim:
111
+ raise ValueError(f"自变量维度不一致:第{i}行有{len(x_row)}个变量,但第一行有{first_dim}个变量")
112
+
113
+ # 检查面板数据平衡性
114
+ entity_time_counts = {}
115
+ for entity, time_period in zip(entity_ids, time_periods):
116
+ key = (entity, time_period)
117
+ if key in entity_time_counts:
118
+ raise ValueError(f"重复的实体-时间组合:实体 '{entity}' 在时间 '{time_period}' 有多个观测值")
119
+ entity_time_counts[key] = True
120
+
121
+ # 检查每个实体的时间点数量
122
+ entity_counts = {}
123
+ for entity in entity_ids:
124
+ entity_counts[entity] = entity_counts.get(entity, 0) + 1
125
+
126
+ unique_entities = len(entity_counts)
127
+ if unique_entities < 2:
128
+ raise ValueError(f"面板数据需要至少2个不同的实体,当前只有{unique_entities}个")
129
+
130
+ # 检查时间点数量
131
+ time_counts = {}
132
+ for time_period in time_periods:
133
+ time_counts[time_period] = time_counts.get(time_period, 0) + 1
134
+
135
+ unique_times = len(time_counts)
136
+ if unique_times < 2:
137
+ raise ValueError(f"面板数据需要至少2个不同的时间点,当前只有{unique_times}个")
138
+
139
+ # 检查是否为平衡面板
140
+ time_counts_per_entity = {}
141
+ for entity in set(entity_ids):
142
+ entity_times = [time for e, time in zip(entity_ids, time_periods) if e == entity]
143
+ time_counts_per_entity[entity] = len(set(entity_times))
144
+
145
+ min_times = min(time_counts_per_entity.values())
146
+ max_times = max(time_counts_per_entity.values())
147
+ if min_times != max_times:
148
+ warnings.warn(f"⚠️ 警告:面板数据不平衡。不同实体的时间点数量不同(最少{min_times}个,最多{max_times}个)。建议使用平衡面板数据以获得更可靠的结果。")
83
149
 
84
150
  # 处理时间标识符格式兼容性
85
151
  processed_time_periods = []
@@ -601,16 +601,62 @@ GRADIENT_BOOSTING_REGRESSION_ANALYSIS = ToolDescription(
601
601
 
602
602
  LASSO_REGRESSION_ANALYSIS = ToolDescription(
603
603
  name="lasso_regression_analysis",
604
- description="Lasso回归 - 支持文件输入",
604
+ description="""Lasso回归分析
605
+
606
+ 📊 功能说明:
607
+ Lasso回归使用L1正则化进行特征选择和稀疏建模,能够自动将不重要的特征系数压缩为0。
608
+
609
+ 📈 算法特点:
610
+ - 特征选择:自动识别重要特征,压缩冗余特征系数为0
611
+ - 稀疏解:产生稀疏的系数向量,提高模型可解释性
612
+ - 处理多重共线性:对高度相关的特征进行选择
613
+ - 正则化强度控制:通过alpha参数控制特征选择的严格程度
614
+
615
+ 💡 适用场景:
616
+ - 高维数据特征选择(特征数量 > 样本数量)
617
+ - 多重共线性问题
618
+ - 稀疏建模需求
619
+ - 可解释性要求高的场景
620
+ - 变量筛选和降维
621
+
622
+ ⚠️ 注意事项:
623
+ - 对alpha参数敏感,建议尝试多个值(如0.01, 0.1, 1.0, 10.0)
624
+ - 可能过度压缩重要特征,导致信息损失
625
+ - 需要数据标准化
626
+ - R²为负值时表明模型性能比简单均值预测更差
627
+ - 样本量过小时可能不稳定
628
+
629
+ 🔧 参数建议:
630
+ - alpha: 正则化强度,默认1.0
631
+ - 小alpha(0.01-0.1): 轻微正则化,保留更多特征
632
+ - 中等alpha(0.1-1.0): 平衡特征选择和模型拟合
633
+ - 大alpha(>1.0): 强正则化,压缩更多特征
634
+
635
+ 📋 数据要求:
636
+ - 至少5个样本
637
+ - 数值型数据
638
+ - 建议特征数量不超过样本数量的80%""",
605
639
  field_descriptions={
606
- "file_path": "文件路径",
607
- "file_content": "文件内容",
608
- "file_format": "文件格式",
609
- "y_data": "因变量数据",
610
- "x_data": "自变量数据",
611
- "feature_names": "特征名称",
612
- "alpha": "正则化参数"
613
- }
640
+ "file_path": "CSV/JSON文件路径。CSV格式: 最后一列为因变量,其余列为自变量",
641
+ "file_content": "文件内容字符串。JSON格式: {'y': [因变量], 'x1': [自变量1], ...}",
642
+ "file_format": "文件格式: csv/json/auto",
643
+ "y_data": "因变量数据列表,数值格式,如 [1.2, 3.4, 5.6, ...]",
644
+ "x_data": "自变量数据矩阵,二维列表格式,如 [[1, 2], [3, 4], [5, 6], ...]",
645
+ "feature_names": "自变量名称列表,如 ['GDP', 'Population', 'Investment']",
646
+ "alpha": "正则化强度参数,控制特征选择的严格程度,默认1.0。建议尝试多个值进行调优"
647
+ },
648
+ examples=[
649
+ "从100个经济指标中选择影响GDP增长的关键因素",
650
+ "在消费者行为数据中识别最重要的预测变量",
651
+ "处理高度相关的宏观经济变量进行预测建模"
652
+ ],
653
+ use_cases=[
654
+ "高维数据特征选择",
655
+ "变量重要性排序",
656
+ "多重共线性处理",
657
+ "稀疏线性建模",
658
+ "可解释机器学习"
659
+ ]
614
660
  )
615
661
 
616
662
  RIDGE_REGRESSION_ANALYSIS = ToolDescription(
@@ -228,28 +228,92 @@ async def handle_correlation_analysis(ctx, data: Dict[str, List[float]],
228
228
 
229
229
 
230
230
  # 面板数据处理器
231
- async def handle_panel_fixed_effects(ctx, y_data, x_data, entity_ids, time_periods,
231
+ async def handle_panel_fixed_effects(ctx, y_data, x_data, entity_ids, time_periods,
232
232
  feature_names=None, entity_effects=True, time_effects=False, **kwargs):
233
+ """处理固定效应模型 - 统一输出格式"""
233
234
  result = fixed_effects_model(y_data, x_data, entity_ids, time_periods, feature_names, entity_effects, time_effects)
235
+
236
+ # 构建详细的结果文本
237
+ result_text = f"""📊 固定效应模型分析结果
238
+
239
+ 🔍 模型拟合信息:
240
+ - R² = {result.rsquared:.4f}
241
+ - 调整R² = {result.rsquared_adj:.4f}
242
+ - F统计量 = {result.f_statistic:.4f} (p = {result.f_pvalue:.4f})
243
+ - AIC = {result.aic:.2f}, BIC = {result.bic:.2f}
244
+ - 观测数量 = {result.n_obs}
245
+ - 个体效应 = {'是' if result.entity_effects else '否'}
246
+ - 时间效应 = {'是' if result.time_effects else '否'}
247
+
248
+ 📈 回归系数详情:"""
249
+
250
+ # 添加系数信息
251
+ for var_name, coef_info in result.coefficients.items():
252
+ significance = "***" if coef_info["p_value"] < 0.01 else "**" if coef_info["p_value"] < 0.05 else "*" if coef_info["p_value"] < 0.1 else ""
253
+ result_text += f"\n- {var_name}: {coef_info['coef']:.4f}{significance} (se={coef_info['std_err']:.4f}, p={coef_info['p_value']:.4f})"
254
+
255
+ result_text += "\n\n💡 模型说明:固定效应模型通过组内变换消除个体固定差异,适用于个体间存在不可观测固定特征的情况。"
256
+
234
257
  return CallToolResult(
235
- content=[TextContent(type="text", text=f"固定效应模型: R²={result.rsquared:.4f}")],
258
+ content=[TextContent(type="text", text=result_text)],
236
259
  structuredContent=result.model_dump()
237
260
  )
238
261
 
239
262
 
240
263
  async def handle_panel_random_effects(ctx, y_data, x_data, entity_ids, time_periods,
241
264
  feature_names=None, entity_effects=True, time_effects=False, **kwargs):
265
+ """处理随机效应模型 - 统一输出格式"""
242
266
  result = random_effects_model(y_data, x_data, entity_ids, time_periods, feature_names, entity_effects, time_effects)
267
+
268
+ # 构建详细的结果文本
269
+ result_text = f"""📊 随机效应模型分析结果
270
+
271
+ 🔍 模型拟合信息:
272
+ - R² = {result.rsquared:.4f}
273
+ - 调整R² = {result.rsquared_adj:.4f}
274
+ - F统计量 = {result.f_statistic:.4f} (p = {result.f_pvalue:.4f})
275
+ - AIC = {result.aic:.2f}, BIC = {result.bic:.2f}
276
+ - 观测数量 = {result.n_obs}
277
+ - 个体效应 = {'是' if result.entity_effects else '否'}
278
+ - 时间效应 = {'是' if result.time_effects else '否'}
279
+
280
+ 📈 回归系数详情:"""
281
+
282
+ # 添加系数信息
283
+ for var_name, coef_info in result.coefficients.items():
284
+ significance = "***" if coef_info["p_value"] < 0.01 else "**" if coef_info["p_value"] < 0.05 else "*" if coef_info["p_value"] < 0.1 else ""
285
+ result_text += f"\n- {var_name}: {coef_info['coef']:.4f}{significance} (se={coef_info['std_err']:.4f}, p={coef_info['p_value']:.4f})"
286
+
287
+ result_text += "\n\n💡 模型说明:随机效应模型假设个体差异是随机的,比固定效应模型更有效率,但需要满足个体效应与解释变量不相关的假设。"
288
+
243
289
  return CallToolResult(
244
- content=[TextContent(type="text", text=f"随机效应模型: R²={result.rsquared:.4f}")],
290
+ content=[TextContent(type="text", text=result_text)],
245
291
  structuredContent=result.model_dump()
246
292
  )
247
293
 
248
294
 
249
295
  async def handle_panel_hausman_test(ctx, y_data, x_data, entity_ids, time_periods, feature_names=None, **kwargs):
296
+ """处理Hausman检验 - 统一输出格式"""
250
297
  result = hausman_test(y_data, x_data, entity_ids, time_periods, feature_names)
298
+
299
+ result_text = f"""📊 Hausman检验结果
300
+
301
+ 🔍 检验信息:
302
+ - 检验统计量 = {result.statistic:.4f}
303
+ - p值 = {result.p_value:.4f}
304
+ - 显著性 = {'是' if result.significant else '否'} (5%水平)
305
+
306
+ 💡 模型选择建议:
307
+ {result.recommendation}
308
+
309
+ 📋 决策规则:
310
+ - p值 < 0.05: 拒绝原假设,选择固定效应模型
311
+ - p值 >= 0.05: 不能拒绝原假设,选择随机效应模型
312
+
313
+ 🔬 检验原理:Hausman检验用于判断个体效应是否与解释变量相关。原假设为随机效应模型是一致的。"""
314
+
251
315
  return CallToolResult(
252
- content=[TextContent(type="text", text=f"Hausman检验: p={result.p_value:.4f}, 建议={result.recommendation}")],
316
+ content=[TextContent(type="text", text=result_text)],
253
317
  structuredContent=result.model_dump()
254
318
  )
255
319
 
@@ -347,17 +411,81 @@ async def handle_gradient_boosting(ctx, y_data, x_data, feature_names=None,
347
411
 
348
412
 
349
413
  async def handle_lasso_regression(ctx, y_data, x_data, feature_names=None, alpha=1.0, **kwargs):
414
+ """处理Lasso回归 - 统一输出格式"""
350
415
  result = lasso_regression(y_data, x_data, feature_names, alpha)
416
+
417
+ # 检查R²是否为负值
418
+ r2_warning = ""
419
+ if result.r2_score < 0:
420
+ r2_warning = f"\n⚠️ 警告:R²为负值({result.r2_score:.4f}),表明模型性能比简单均值预测更差。建议:1) 检查数据质量 2) 尝试更小的alpha值 3) 增加样本数量"
421
+
422
+ # 检查系数是否全为0
423
+ coef_warning = ""
424
+ if all(abs(coef) < 1e-10 for coef in result.coefficients.values()):
425
+ coef_warning = f"\n⚠️ 警告:所有系数都被压缩为0,正则化参数alpha={alpha}可能过大,建议减小alpha值"
426
+
427
+ # 构建详细的结果文本
428
+ result_text = f"""📊 Lasso回归分析结果
429
+
430
+ 🔍 模型拟合信息:
431
+ - R² = {result.r2_score:.4f}
432
+ - 均方误差(MSE) = {result.mse:.4f}
433
+ - 平均绝对误差(MAE) = {result.mae:.4f}
434
+ - 样本数量 = {result.n_obs}
435
+ - 正则化参数(alpha) = {result.alpha}
436
+ {r2_warning}{coef_warning}
437
+
438
+ 📈 回归系数详情:"""
439
+
440
+ # 添加系数信息,按绝对值排序
441
+ sorted_coefficients = sorted(result.coefficients.items(), key=lambda x: abs(x[1]), reverse=True)
442
+ for var_name, coef in sorted_coefficients:
443
+ if abs(coef) > 1e-10: # 只显示非零系数
444
+ result_text += f"\n- {var_name}: {coef:.4f}"
445
+ else:
446
+ result_text += f"\n- {var_name}: 0.0000 (被压缩)"
447
+
448
+ result_text += f"\n\n💡 模型说明:Lasso回归使用L1正则化进行特征选择,能够自动将不重要的特征系数压缩为0,适用于高维数据和特征选择场景。"
449
+ result_text += f"\n\n⚠️ 注意事项:由于数据标准化,系数大小需要谨慎解释。"
450
+
351
451
  return CallToolResult(
352
- content=[TextContent(type="text", text=f"Lasso回归: R²={result.r2_score:.4f}")],
452
+ content=[TextContent(type="text", text=result_text)],
353
453
  structuredContent=result.model_dump()
354
454
  )
355
455
 
356
456
 
357
457
  async def handle_ridge_regression(ctx, y_data, x_data, feature_names=None, alpha=1.0, **kwargs):
458
+ """处理Ridge回归 - 统一输出格式"""
358
459
  result = ridge_regression(y_data, x_data, feature_names, alpha)
460
+
461
+ # 检查R²是否为负值
462
+ r2_warning = ""
463
+ if result.r2_score < 0:
464
+ r2_warning = f"\n⚠️ 警告:R²为负值({result.r2_score:.4f}),表明模型性能比简单均值预测更差。建议:1) 检查数据质量 2) 尝试更小的alpha值 3) 增加样本数量"
465
+
466
+ # 构建详细的结果文本
467
+ result_text = f"""📊 Ridge回归分析结果
468
+
469
+ 🔍 模型拟合信息:
470
+ - R² = {result.r2_score:.4f}
471
+ - 均方误差(MSE) = {result.mse:.4f}
472
+ - 平均绝对误差(MAE) = {result.mae:.4f}
473
+ - 样本数量 = {result.n_obs}
474
+ - 正则化参数(alpha) = {result.alpha}
475
+ {r2_warning}
476
+
477
+ 📈 回归系数详情:"""
478
+
479
+ # 添加系数信息,按绝对值排序
480
+ sorted_coefficients = sorted(result.coefficients.items(), key=lambda x: abs(x[1]), reverse=True)
481
+ for var_name, coef in sorted_coefficients:
482
+ result_text += f"\n- {var_name}: {coef:.4f}"
483
+
484
+ result_text += f"\n\n💡 模型说明:Ridge回归使用L2正则化处理多重共线性问题,对所有系数进行收缩但不进行特征选择,适用于需要稳定估计的场景。"
485
+ result_text += f"\n\n⚠️ 注意事项:由于数据标准化,系数大小需要谨慎解释。"
486
+
359
487
  return CallToolResult(
360
- content=[TextContent(type="text", text=f"Ridge回归: R²={result.r2_score:.4f}")],
488
+ content=[TextContent(type="text", text=result_text)],
361
489
  structuredContent=result.model_dump()
362
490
  )
363
491