Spaces:
Runtime error
Runtime error
File size: 11,848 Bytes
6a18a7f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 | 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"]
@dataclass(frozen=True)
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
|