Spaces:
Runtime error
Runtime error
| from __future__ import annotations | |
| from dataclasses import dataclass | |
| from typing import Any, Literal | |
| import pandas as pd | |
| ParameterType = Literal["int", "float", "bool", "str", "optional_int", "optional_float", "tuple_int"] | |
| class Parameter: | |
| name: str | |
| default: Any | |
| kind: ParameterType | |
| description: str | |
| def p(name: str, default: Any, kind: ParameterType, description: str) -> Parameter: | |
| return Parameter(name, default, kind, description) | |
| HYPERPARAMETER_SCHEMAS: dict[str, list[Parameter]] = { | |
| "MLP": [ | |
| p("hidden_layer_sizes", (64, 32), "tuple_int", "隐藏层神经元,例如 128,64"), | |
| p("activation", "relu", "str", "激活函数:relu / tanh / logistic / identity"), | |
| p("solver", "adam", "str", "优化器:adam / sgd / lbfgs"), | |
| p("alpha", 0.0001, "float", "L2 正则强度"), | |
| p("batch_size", "auto", "str", "批大小;auto 或整数"), | |
| p("learning_rate", "constant", "str", "学习率策略:constant / invscaling / adaptive"), | |
| p("learning_rate_init", 0.001, "float", "初始学习率"), | |
| p("power_t", 0.5, "float", "invscaling 学习率指数"), | |
| p("max_iter", 1000, "int", "最大训练迭代次数"), | |
| p("shuffle", True, "bool", "每轮是否打乱样本"), | |
| p("tol", 0.0001, "float", "优化停止容差"), | |
| p("warm_start", False, "bool", "是否复用上次训练结果"), | |
| p("momentum", 0.9, "float", "SGD 动量"), | |
| p("nesterovs_momentum", True, "bool", "是否使用 Nesterov 动量"), | |
| p("early_stopping", False, "bool", "验证集长期无提升时提前停止;小数据建议 false"), | |
| p("validation_fraction", 0.1, "float", "提前停止验证集比例"), | |
| p("beta_1", 0.9, "float", "Adam 一阶矩衰减"), | |
| p("beta_2", 0.999, "float", "Adam 二阶矩衰减"), | |
| p("epsilon", 1e-8, "float", "Adam 数值稳定项"), | |
| p("n_iter_no_change", 20, "int", "允许无提升的迭代轮数"), | |
| p("max_fun", 20000, "int", "LBFGS 最大函数调用次数"), | |
| ], | |
| "Random Forest": [ | |
| p("n_estimators", 240, "int", "树的数量"), | |
| p("criterion", "auto", "str", "划分标准;auto 根据任务选择"), | |
| p("max_depth", None, "optional_int", "单棵树最大深度;none 不限制"), | |
| p("min_samples_split", 2, "int", "内部节点继续划分的最少样本"), | |
| p("min_samples_leaf", 1, "int", "叶节点最少样本"), | |
| p("min_weight_fraction_leaf", 0.0, "float", "叶节点最小权重比例"), | |
| p("max_features", "auto", "str", "每次划分考察的特征数"), | |
| p("max_leaf_nodes", None, "optional_int", "最大叶节点数"), | |
| p("min_impurity_decrease", 0.0, "float", "最小不纯度下降"), | |
| p("bootstrap", True, "bool", "是否 bootstrap 采样"), | |
| p("oob_score", False, "bool", "是否计算袋外分数"), | |
| p("n_jobs", -1, "int", "并行任务数;-1 使用全部核心"), | |
| p("warm_start", False, "bool", "是否追加训练更多树"), | |
| p("class_weight", None, "str", "分类权重:none / balanced / balanced_subsample"), | |
| p("ccp_alpha", 0.0, "float", "成本复杂度剪枝强度"), | |
| p("max_samples", None, "optional_float", "每棵树 bootstrap 样本比例"), | |
| ], | |
| "Extra Trees": [ | |
| p("n_estimators", 240, "int", "树的数量"), | |
| p("criterion", "auto", "str", "划分标准;auto 根据任务选择"), | |
| p("max_depth", None, "optional_int", "单棵树最大深度"), | |
| p("min_samples_split", 2, "int", "内部节点最少样本"), | |
| p("min_samples_leaf", 1, "int", "叶节点最少样本"), | |
| p("min_weight_fraction_leaf", 0.0, "float", "叶节点最小权重比例"), | |
| p("max_features", "auto", "str", "每次划分考察的特征数"), | |
| p("max_leaf_nodes", None, "optional_int", "最大叶节点数"), | |
| p("min_impurity_decrease", 0.0, "float", "最小不纯度下降"), | |
| p("bootstrap", False, "bool", "是否 bootstrap 采样"), | |
| p("oob_score", False, "bool", "是否计算袋外分数"), | |
| p("n_jobs", -1, "int", "并行任务数"), | |
| p("warm_start", False, "bool", "是否追加训练"), | |
| p("class_weight", None, "str", "分类权重"), | |
| p("ccp_alpha", 0.0, "float", "成本复杂度剪枝"), | |
| p("max_samples", None, "optional_float", "bootstrap 样本比例"), | |
| ], | |
| "Gradient Boosting": [ | |
| p("loss", "auto", "str", "损失函数;auto 根据任务选择"), | |
| p("learning_rate", 0.05, "float", "每棵树的贡献缩放"), | |
| p("n_estimators", 180, "int", "提升阶段数量"), | |
| p("subsample", 0.9, "float", "每阶段使用的样本比例"), | |
| p("criterion", "friedman_mse", "str", "树划分标准"), | |
| p("min_samples_split", 2, "int", "内部节点最少样本"), | |
| p("min_samples_leaf", 1, "int", "叶节点最少样本"), | |
| p("min_weight_fraction_leaf", 0.0, "float", "叶节点最小权重比例"), | |
| p("max_depth", 3, "int", "基学习器最大深度"), | |
| p("min_impurity_decrease", 0.0, "float", "最小不纯度下降"), | |
| p("max_features", None, "str", "每次划分使用的特征数"), | |
| p("alpha", 0.9, "float", "Huber/Quantile 分位数"), | |
| p("max_leaf_nodes", None, "optional_int", "最大叶节点数"), | |
| p("warm_start", False, "bool", "是否追加提升阶段"), | |
| p("validation_fraction", 0.1, "float", "提前停止验证比例"), | |
| p("n_iter_no_change", None, "optional_int", "无提升提前停止轮数"), | |
| p("tol", 0.0001, "float", "提前停止容差"), | |
| p("ccp_alpha", 0.0, "float", "基学习器剪枝强度"), | |
| ], | |
| "SVM": [ | |
| p("C", 2.0, "float", "正则化强度的倒数"), | |
| p("kernel", "rbf", "str", "核函数:rbf / linear / poly / sigmoid"), | |
| p("degree", 3, "int", "多项式核次数"), | |
| p("gamma", "scale", "str", "核系数:scale / auto / 数值"), | |
| p("coef0", 0.0, "float", "poly/sigmoid 核独立项"), | |
| p("shrinking", True, "bool", "是否使用 shrinking 启发式"), | |
| p("probability", True, "bool", "分类时启用概率估计"), | |
| p("tol", 0.001, "float", "停止容差"), | |
| p("cache_size", 300, "float", "核缓存大小 MB"), | |
| p("class_weight", None, "str", "分类权重:none / balanced"), | |
| p("max_iter", -1, "int", "最大迭代;-1 不限制"), | |
| p("decision_function_shape", "ovr", "str", "多分类决策:ovr / ovo"), | |
| p("break_ties", False, "bool", "分类平票时按置信度裁决"), | |
| p("epsilon", 0.1, "float", "SVR epsilon-insensitive 区间"), | |
| ], | |
| "KNN": [ | |
| p("n_neighbors", 7, "int", "参与预测的邻居数量"), | |
| p("weights", "distance", "str", "邻居权重:uniform / distance"), | |
| p("algorithm", "auto", "str", "近邻搜索:auto / ball_tree / kd_tree / brute"), | |
| p("leaf_size", 30, "int", "树结构叶大小"), | |
| p("p", 2, "float", "Minkowski 距离指数"), | |
| p("metric", "minkowski", "str", "距离度量"), | |
| p("n_jobs", -1, "int", "并行任务数"), | |
| ], | |
| "Decision Tree": [ | |
| p("criterion", "auto", "str", "划分标准;auto 根据任务选择"), | |
| p("splitter", "best", "str", "划分策略:best / random"), | |
| p("max_depth", 12, "optional_int", "最大树深"), | |
| p("min_samples_split", 2, "int", "内部节点最少样本"), | |
| p("min_samples_leaf", 1, "int", "叶节点最少样本"), | |
| p("min_weight_fraction_leaf", 0.0, "float", "叶节点最小权重比例"), | |
| p("max_features", None, "str", "划分使用的特征数"), | |
| p("max_leaf_nodes", None, "optional_int", "最大叶节点数"), | |
| p("min_impurity_decrease", 0.0, "float", "最小不纯度下降"), | |
| p("class_weight", None, "str", "分类权重"), | |
| p("ccp_alpha", 0.0, "float", "成本复杂度剪枝"), | |
| ], | |
| "Logistic Regression": [ | |
| p("penalty", "l2", "str", "正则类型:l1 / l2 / elasticnet / none"), | |
| p("C", 1.0, "float", "正则化强度的倒数"), | |
| p("l1_ratio", 0.0, "float", "Elastic Net 的 L1 比例"), | |
| p("dual", False, "bool", "是否使用对偶问题"), | |
| p("tol", 0.0001, "float", "停止容差"), | |
| p("fit_intercept", True, "bool", "是否拟合截距"), | |
| p("intercept_scaling", 1.0, "float", "liblinear 截距缩放"), | |
| p("class_weight", None, "str", "类别权重:none / balanced"), | |
| p("solver", "lbfgs", "str", "求解器:lbfgs / liblinear / saga 等"), | |
| p("max_iter", 500, "int", "最大迭代次数"), | |
| p("warm_start", False, "bool", "是否复用上次解"), | |
| p("n_jobs", -1, "int", "并行任务数"), | |
| ], | |
| "Linear Regression": [ | |
| p("fit_intercept", True, "bool", "是否拟合截距"), | |
| p("copy_X", True, "bool", "是否复制输入特征"), | |
| p("tol", 1e-6, "float", "稀疏求解停止容差"), | |
| p("n_jobs", -1, "int", "并行任务数"), | |
| p("positive", False, "bool", "是否约束系数为非负"), | |
| ], | |
| } | |
| def _display(value: Any) -> str: | |
| if value is None: | |
| return "none" | |
| if isinstance(value, tuple): | |
| return ",".join(str(item) for item in value) | |
| if isinstance(value, bool): | |
| return str(value).lower() | |
| return str(value) | |
| def default_parameter_frame(algorithm: str) -> pd.DataFrame: | |
| if algorithm not in HYPERPARAMETER_SCHEMAS: | |
| raise ValueError(f"未知算法:{algorithm}") | |
| return pd.DataFrame( | |
| [ | |
| { | |
| "Parameter": parameter.name, | |
| "Value": _display(parameter.default), | |
| "Description": parameter.description, | |
| } | |
| for parameter in HYPERPARAMETER_SCHEMAS[algorithm] | |
| ] | |
| ) | |
| def _parse_value(parameter: Parameter, raw: Any) -> Any: | |
| value = str(raw).strip() | |
| lower = value.lower() | |
| if parameter.kind in {"optional_int", "optional_float"} and lower in {"none", "null", ""}: | |
| return None | |
| if parameter.kind == "bool": | |
| if lower not in {"true", "false"}: | |
| raise ValueError("需要 true 或 false") | |
| return lower == "true" | |
| if parameter.kind in {"int", "optional_int"}: | |
| return int(float(value)) | |
| if parameter.kind in {"float", "optional_float"}: | |
| return float(value) | |
| if parameter.kind == "tuple_int": | |
| return tuple(int(item.strip()) for item in value.split(",") if item.strip()) | |
| if lower in {"none", "null"}: | |
| return None | |
| if parameter.name == "batch_size": | |
| return int(value) if lower != "auto" else "auto" | |
| if parameter.name == "max_features": | |
| try: | |
| return float(value) if "." in value else int(value) | |
| except ValueError: | |
| return value | |
| if parameter.name == "gamma": | |
| try: | |
| return float(value) | |
| except ValueError: | |
| return value | |
| return value | |
| def parse_parameter_frame(algorithm: str, frame: pd.DataFrame | list[list[Any]]) -> dict[str, Any]: | |
| schema = {parameter.name: parameter for parameter in HYPERPARAMETER_SCHEMAS[algorithm]} | |
| data = frame if isinstance(frame, pd.DataFrame) else pd.DataFrame(frame) | |
| if list(data.columns) != ["Parameter", "Value", "Description"]: | |
| data.columns = ["Parameter", "Value", "Description"] | |
| parsed: dict[str, Any] = {} | |
| for _, row in data.iterrows(): | |
| name = str(row["Parameter"]).strip() | |
| if name not in schema: | |
| raise ValueError(f"未知超参数:{name}") | |
| try: | |
| parsed[name] = _parse_value(schema[name], row["Value"]) | |
| except (TypeError, ValueError) as exc: | |
| raise ValueError(f"超参数 {name} 的值无效:{row['Value']}") from exc | |
| return parsed | |