Basalt»3.4.0»API 参考»basalt.ml
模块 索引 GitHub

模块 basalt.ml

102 个公开类型 · 14 个包内可见类型

经典机器学习:线性模型、近邻、SVM、树、梯度提升、聚类、降维、朴素贝叶斯、指标与切分。

类型概览

类型种类说明
AgglomerativeClusteringclass自底向上合并的层次聚类,支持四种链接准则。
BoostingAlgorithmenum直方图树的生长策略:深度优先或叶优先
BoostingObjectiveenum直方图提升支持的目标:平方误差与二分类逻辑
DBSCANclass按 eps 邻域与 minPoints 判定核心点的密度聚类。
DataSplitclass基于行下标的确定性 holdout、k 折与分层 k 折划分。
DecisionTreeclass预分箱特征上的 CART 树,分裂搜索走直方图
DistanceMetricenumKNN 使用的距离函数枚举。
EigenSolverenumPCA 可选的对称特征分解求解器。
Estimatorinterface经典估计器的统一契约。
Estimatorsclass按枚举选择算法的一行式门面。
FeatureImportanceclass统一的特征重要性入口:树杂质、线性权重绝对值与置换重要性。
GaussianMixtureclassEM 估计的高斯混合模型,协方差可选 FULL / TIED / DIAG。
GaussianNaiveBayesclass按类估计均值、方差与先验的高斯朴素贝叶斯分类器。
GridSearchCVclass网格穷举加交叉验证的调参器,选优后全量重训。
HistogramGradientBoostingclass二阶直方图梯度提升,支持深度优先与叶优先生长
ImpurityCriterionenum决策树用于最大化信息增益的节点不纯度
IsolationForestclass随机轴对齐切分的无监督孤立森林异常检测器。
KBinsDiscretizerclass按分位数、等宽或一维 K-Means 把连续特征离散为箱。
KFoldclassK 折交叉验证划分器,默认打乱且种子为 42。
KMeansclassK-Means++ 播种的 Lloyd 迭代聚类,支持多次重启。
KNearestNeighborsclass统一权重的 KNN 分类器。
KNeighborsRegressorclass统一权重的 KNN 回归器。
Kernelclass四种半正定核函数:LINEAR、RBF、POLY 与 SIGMOID。
KernelDensityclass高斯与 TOPHAT 核的核密度估计,输出对数密度。
KernelPCAclass核主成分分析:在核空间中心化后做特征分解的降维估计器。
KernelRidgeclass核岭回归:在核空间解 (K + alpha·I)α = y 的回归估计器。
LabelEncoderclass把类别标签双向映射为 0..k-1 整数码的编码器。
Lassoclass坐标下降求解的 L1 正则最小二乘。
LimeExplainerclass用局部加权线性代理模型解释单个预测的 LIME 解释器。
LinearRegressionclass全批量梯度下降的普通最小二乘。
LinearSVMclassPEGASOS 次梯度法训练的二分类线性 SVM。
LogisticRegressionclass全批量梯度下降的二分类逻辑回归。
Metricsclass分类与回归指标,纯 Java 实现。
MinMaxScalerclass按列线性映射到指定区间的缩放器。
OneHotEncoderclass把类别列展开为稠密 0/1 指示特征的编码器。
PCAclass中心化主成分分析,含协方差与 Gram 两条精确路径。
Pipelineclass顺序串联预处理步骤与最终估计器的管道
PolynomialFeaturesclass生成最高到 degree 的多项式与交互特征
RFEclass按重要性递归剔除特征直到保留指定数量
RandomForestclass自助聚合的直方图森林,节点级特征子采样
RandomizedSearchCVclass按参数分布随机采样并交叉验证选优
RidgeclassCholesky 求解的 L2 正则最小二乘。
SVCclassSMO 求解的核支持向量分类器,支持 OvR 多分类与 Platt 概率校准。
SelectKBestclass按单变量统计量保留得分最高的 k 个特征
ShapExplainerclass计算可加的 SHAP 归因值,满足 Σφ = f(x) − E[f]
SimpleImputerclass用列统计量填补 NaN 缺失值
StandardScalerclass按列去均值并缩放到单位方差
StratifiedKFoldclass保持类别比例的分层 K 折划分器
Transformerinterface有状态特征预处理与特征工程步骤的统一契约
TreeTaskenum单棵决策树的监督目标:分类或回归
AgglomerativeClustering.BuilderclassAgglomerativeClustering 的构建器。
AgglomerativeClustering.Linkageenum层次聚类的簇间连接准则
DBSCAN.BuilderclassDBSCAN 的构建器,设置邻域半径、密度阈值与距离度量。
DataSplit.Foldrecord一折的训练与测试四元组。
DataSplit.Holdoutrecord一次 holdout 划分的四元组。
DecisionTree.BuilderclassDecisionTree 的流式构造器
Estimators.Algorithmenum门面可选算法及其任务类型。
Estimators.Metricenum交叉验证可选的评估指标。
Estimators.Taskenum算法的任务类型分类。
FeatureImportance.PermutationResultrecord置换重要性的计算结果,含逐次重复的原始分数。
GaussianMixture.BuilderclassGaussianMixture 的构建器。
GaussianMixture.CovarianceTypeenumGMM 的协方差参数化方式。
GaussianNaiveBayes.BuilderclassGaussianNaiveBayes 的构建器。
GridSearchCV.BuilderclassGridSearchCV 的构建器,登记参数网格与交叉验证策略。
GridSearchCV.CandidateResultrecord网格搜索中单个参数组合的交叉验证结果快照。
HistogramGradientBoosting.BuilderclassHistogramGradientBoosting 的流式构造器
IsolationForest.BuilderclassIsolationForest 的流式构建器。
KBinsDiscretizer.BuilderclassKBinsDiscretizer 的流式构建器。
KBinsDiscretizer.Encodeenum离散化结果的编码方式。
KBinsDiscretizer.Strategyenum分箱边界的计算策略。
KMeans.BuilderclassKMeans 的构建器,设置簇数、迭代上限、收敛阈值与随机种子。
KNearestNeighbors.BuilderclassKNearestNeighbors 的流式构建器。
KNeighborsRegressor.BuilderclassKNeighborsRegressor 的流式构建器。
Kernel.TypeenumKernel 支持的四种半正定核函数类型。
KernelDensity.BuilderclassKernelDensity 的流式构建器。
KernelDensity.KernelTypeenum核密度估计可用的核函数类型。
KernelPCA.BuilderclassKernelPCA 的流式构建器。
KernelRidge.BuilderclassKernelRidge 的流式构建器。
Lasso.BuilderclassLasso 的流式构建器。
LimeExplainer.LocalExplanationrecordLIME 对单个样本的局部解释结果。
LinearRegression.BuilderclassLinearRegression 的流式构建器。
LinearSVM.BuilderclassLinearSVM 的流式构建器。
LogisticRegression.BuilderclassLogisticRegression 的流式构建器。
MinMaxScaler.BuilderclassMinMaxScaler 的流式构建器。
OneHotEncoder.BuilderclassOneHotEncoder 的流式构建器。
OneHotEncoder.HandleUnknownenumtransform 遇到未见类别时的处理策略。
PCA.BuilderclassPCA 的构建器,设置分量数、求解器、扫描上限与白化开关。
Pipeline.BuilderclassPipeline 的构造器,按序追加步骤并挂接末端估计器。
Pipeline.Steprecord流水线中的具名步骤:名称与变换器的不可变组合。
PolynomialFeatures.BuilderclassPolynomialFeatures 的构造器,设置阶数与偏置项。
RFE.BuilderclassRFE 的构造器,设置保留特征数与淘汰步长。
RandomForest.BuilderclassRandomForest 的流式构造器
RandomizedSearchCV.Builderclass随机搜索的构造器,登记参数分布与分折策略。
RandomizedSearchCV.ParameterSamplerinterface参数分布的抽样接口,单方法返回一个参数值。
Ridge.BuilderclassRidge 的流式构建器。
SVC.BuilderclassSVC 的构造器,设置核函数、惩罚系数与 SMO 参数。
SelectKBest.BuilderclassSelectKBest 的构造器,设置保留数与评分函数。
SelectKBest.ScoreFuncenum特征打分的统计检验:分类 F、回归 F、卡方
ShapExplainer.Explanationrecord一次解释的结果:基准值、SHAP 矩阵、预测与平均绝对值
SimpleImputer.Builderclass构造 SimpleImputer,设置缺失值策略与常数填充值
SimpleImputer.Strategyenum缺失值填充策略:均值、中位数、众数、常数
StandardScaler.Builderclass构造 StandardScaler,设置是否中心化与是否缩放
final class AgglomerativeClustering implements Estimator

自底向上合并的层次聚类,支持四种链接准则。

拟合从每个样本各自成簇开始,反复合并代价最小的一对活跃簇,直到剩余簇数等于 clusters。初始距离矩阵保存全部样本对的欧氏距离,占用 n×n 个 double,构造耗时为 O(n²p);此后每轮合并都要扫描所有活跃簇对,共 n−clusters 轮,整体时间达到 O(n³)。因此该实现适合中小规模数据,样本数上万时距离矩阵本身就难以承受。

四种准则的差别在选择合并对时的代价:SINGLE 取两簇间最近样本的距离,倾向于串起长链,能发现非凸形状但易受噪声牵连;COMPLETE 取最远样本距离,产生紧致且直径相近的簇;AVERAGE 取簇间全部样本对距离的均值,介于两者之间,对噪声更稳健;WARD 用 (ni·nj/(ni+nj))·‖μi−μj‖² 衡量合并带来的方差增量,倾向等方差的球形簇。

合并后距离矩阵就地更新:SINGLE 取 min、COMPLETE 取 max、AVERAGE 与 WARD 都取按簇大小加权的平均 (sizeA·dAK + sizeB·dBK)/(sizeA+sizeB)。簇编号在合并结束后按活跃簇的下标升序重编为 0 起,与合并先后无关。

示例
Matrix features = Matrix.fromRows(new double[][] {
    {0.0, 0.0}, {0.2, 0.1}, {0.1, 0.3},
    {5.0, 5.0}, {5.2, 4.9}, {4.8, 5.1}
});
AgglomerativeClustering model = AgglomerativeClustering.builder()
        .clusters(2)
        .linkage(AgglomerativeClustering.Linkage.WARD)
        .build()
        .fit(features);
int[] labels = model.labels();
double[] assigned = model.predict(features);

注意

WARD 的选择代价与距离矩阵的更新公式并不相同:前者是方差增量,后者是加权平均距离

注意

只有 fit 而没有 fitPredict,训练标签通过 labels() 读取

注意

predict 在输入与拟合数据逐元素相同时直接返回训练标签,否则按到最终簇均值的平方欧氏距离归属,属于质心近似而非层次归属

注意

clusters 必须为正且不超过样本数,后者在 fit 时校验

参见:basalt.ml.Estimator, basalt.ml.KMeans, basalt.ml.DBSCAN

方法

builder() → Builderstatic

创建 AgglomerativeClustering 构建器。

返回

clusters 为 2、linkage 为 WARD 的新 Builder 实例

fit(Matrix features) → AgglomerativeClustering

以无监督方式执行层次聚类。

等价于 fit(features, null),目标数组不参与任何计算。

参数
  • features (Matrix) – 样本矩阵,行是样本、列是特征;元素必须有限

返回

this,便于链式调用

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – features 含非有限值,或 clusters 大于样本数

fit(Matrix features, double[] ignoredTargets) → AgglomerativeClustering

在给定特征上执行自底向上的合并聚类。

先复制输入特征,建立 n×n 的欧氏距离矩阵,再循环挑选代价最小的活跃簇对并合并:合并后的均值按两簇样本数加权,被合并行的距离按链接准则更新,另一簇标为非活跃。簇数降到 clusters 时停止。

注意

重复调用 fit 会重建距离矩阵与标签,上一次结果被覆盖

注意

样本数等于 clusters 时不发生任何合并,每个样本自成一簇

参数
  • features (Matrix) – 样本矩阵,行是样本、列是特征;元素必须有限

  • ignoredTargets (double[]) – 占位参数;聚类为无监督任务,源码不读取,传 null 或任意数组均可

返回

this,便于链式调用

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – features 含非有限值,或 clusters 大于样本数

predict(Matrix features) → double[]

把样本归入最近的最终簇均值。

输入与拟合数据行数相同且底层数组逐元素相等时,直接返回训练标签的副本;否则逐行计算到 clusters 个簇均值的平方欧氏距离并取最小者。距离比较用严格小于,平局时返回编号较小的簇。

参数
  • features (Matrix) – 样本矩阵,列数须等于拟合时的特征数;元素必须有限

返回

长度为样本数的簇编号数组,取值 0 到 clusters−1

抛出
  • NullPointerException – features 为 null

  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 特征列数与拟合时不一致,或含非有限值

labels() → int[]

返回训练样本的簇标签副本。

簇编号从 0 开始,按合并结束后活跃簇的下标升序编号,因此同一份输入的编号与 linkage 无关。返回 clone,修改它不影响模型状态。

返回

长度等于训练样本数的标签数组

抛出
  • IllegalStateException – 尚未拟合

linkage() → Linkage

返回构造时指定的链接准则。

返回

Linkage 常量(WARD、COMPLETE、AVERAGE 或 SINGLE);未拟合时同样返回配置值

enum BoostingAlgorithm

直方图树的生长策略:深度优先或叶优先

XGBOOST 按层递归生长:节点在深度小于 maxDepth 且增益为正时分裂,左右子树继续递归,树的叶数由深度与数据决定。LIGHTGBM 维护一个按增益降序排列的候选叶队列,每轮分裂全局增益最大的叶,直到叶数达到 maxLeaves。

示例
HistogramGradientBoosting depthWise = HistogramGradientBoosting.builder()
        .algorithm(BoostingAlgorithm.XGBOOST)
        .maxDepth(4)
        .build();

HistogramGradientBoosting leafWise = HistogramGradientBoosting.builder()
        .algorithm(BoostingAlgorithm.LIGHTGBM)
        .maxLeaves(15)
        .build();

注意

XGBOOST 策略不读取 maxLeaves

注意

LIGHTGBM 策略同时受 maxDepth 约束,每分裂一次叶数加一

参见:basalt.ml.HistogramGradientBoosting

枚举成员

XGBOOST()

深度优先(level-wise)逐层分裂节点

LIGHTGBM()

叶子优先(leaf-wise)按最大增益继续分裂

enum BoostingObjective

直方图提升支持的目标:平方误差与二分类逻辑

SQUARED_ERROR 取残差 raw - target 为梯度、hessian 恒为 1,叶权重等于负梯度除以 hessian 加 lambda。LOGISTIC 取概率减标签为梯度、p(1-p) 为 hessian(下限 1e-12),baseScore 为训练集正类均值的对数几率。

示例
HistogramGradientBoosting classifier = HistogramGradientBoosting.builder()
        .objective(BoostingObjective.LOGISTIC)
        .iterations(200)
        .build();

注意

LOGISTIC 的 fit 会逐行校验标签,出现 0 与 1 之外的值即抛 IllegalArgumentException

注意

predictProbability 只在 LOGISTIC 下可用,其他目标调用会抛 IllegalStateException

参见:basalt.ml.HistogramGradientBoosting

枚举成员

SQUARED_ERROR()

平方误差,用于回归

LOGISTIC()

二分类逻辑损失

final class DBSCAN implements Estimator

按 eps 邻域与 minPoints 判定核心点的密度聚类。

以 eps 为半径的邻域内样本数不少于 minPoints 的点为核心点,簇从核心点出发按广度优先扩展。边界点归入首个到达它的簇,无法从任何核心点到达的点保留噪声标签 -1。

邻域查询逐点线性扫描全部样本,整体需要 O(n²) 次距离计算,适用于中小规模数据。拟合时复制输入特征,后续 predict 与标签查询都基于这份副本。

示例
Matrix features = Matrix.fromRows(new double[][] {
    {0.0, 0.0}, {0.3, 0.1}, {0.1, 0.4},
    {5.0, 5.0}, {5.2, 4.8}, {4.9, 5.3},
    {9.0, 0.5}
});
DBSCAN dbscan = DBSCAN.builder()
        .eps(0.6)
        .minPoints(3)
        .metric(DistanceMetric.EUCLIDEAN)
        .build()
        .fit(features, null);
int[] labels = dbscan.labels();
int clusters = dbscan.clusterCount();
int noise = dbscan.noiseCount();

注意

minPoints 统计包含点自身,因为点与自身的距离为 0 且不大于 eps

注意

predict 在全部核心点中取 eps 内的最近邻并返回其标签,未命中时返回 -1;这是近似归属,不是密度可达判定

注意

DBSCAN 只实现 Estimator,没有 fit(Matrix) 单参数重载,也没有 write/read

参见:basalt.ml.DistanceMetric, basalt.ml.Estimator

方法

builder() → Builderstatic

创建 DBSCAN 构建器。

返回

参数取默认值的新 Builder 实例

fit(Matrix features, double[] ignoredTargets) → DBSCAN

在给定特征上执行密度聚类并返回自身。

先复制特征矩阵,再把全部标签初始化为 -1,然后按样本顺序扫描:邻域样本数达到 minPoints 的点成为新簇的种子,队列向外扩展直到没有新的核心点可达。

注意

重复调用 fit 会丢弃上一次的标签与核心点标记

参数
  • features (Matrix) – 样本矩阵,行是样本、列是特征;元素必须有限

  • ignoredTargets (double[]) – 占位参数;聚类为无监督任务,传 null 或任意数组都被忽略

返回

this,便于链式调用

抛出
  • IllegalArgumentException – features 为 null 或包含非有限值

predict(Matrix features) → double[]

按最近核心点的标签预测样本所属簇。

对每个待预测样本,在全部核心点中寻找 eps 邻域内距离最近的一个,返回该核心点的簇标签;邻域内不存在核心点时返回 -1。边界点不参与查询,因此结果可能比训练标签更保守。

参数
  • features (Matrix) – 样本矩阵,列数须与拟合时一致

返回

长度为样本数的标签数组,噪声或未命中为 -1

抛出
  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 特征列数与拟合时不一致

labels() → int[]

返回训练样本的簇标签副本。

簇编号从 0 开始,按种子点的发现顺序递增;噪声点保持 -1。返回的是副本,修改它不影响模型状态;未拟合时返回 null。

返回

长度等于训练样本数的标签数组;未拟合时为 null

clusterCount() → int

返回拟合得到的簇数量。

返回

簇数,不含噪声;未拟合时为 0

noiseCount() → int

统计标签为负的样本数量。

注意

直接遍历内部标签数组,未拟合时该数组为 null,调用会抛 NullPointerException

返回

标签小于 0 的样本个数

final class DataSplit

基于行下标的确定性 holdout、k 折与分层 k 折划分。

holdout 与两个 trainTestSplit 重载都先用 seed 构造 Random,对行下标数组做 Fisher-Yates 洗牌,再按洗牌后的顺序切片;两个 kFold 重载复用同一套下标洗牌,把洗牌顺序切成 folds 段连续区间。相同 seed 与相同输入必然产生相同切分,与标签分布无关。

返回的特征与标签都是新建副本,调用方修改切分结果不会影响原始数据。holdout 的测试行数取 round(rows·testFraction) 后夹到 [1, rows−1];kFold 的每折测试块大小相差不超过 1。

stratifiedKFold 与 trainTestSplit 的 stratify 分支改为按目标值分组:每类内部独立洗牌,再用跨类连续的轮转把行分发到各折或切出测试行,使每侧都保留全部类别。某个类别的样本数少于折数时 stratifiedKFold 直接拒绝,因为无法保证每折都有该类样本。

示例
Matrix x = Matrix.fromRows(new double[][]{{0, 0}, {0, 1}, {1, 0}, {1, 1}, {2, 2}, {2, 1}});
double[] y = {0, 0, 1, 1, 1, 1};
DataSplit.Holdout split = DataSplit.holdout(x, y, 0.25, 42L);
LinearRegression model = LinearRegression.builder().build()
        .fit(split.trainFeatures(), split.trainTargets());
double[] predicted = model.predict(split.testFeatures());

注意

holdout 与 kFold 不做分层,类别偏斜时小测试块可能缺少某一类;需要类别均衡时改用 stratifiedKFold 或 stratify 分支

注意

洗牌只重排行,不改变列顺序与数值

注意

所有入口都会先做非空、行数一致与非有限值校验

注意

testFraction 取开区间 (0, 1);分层分支的实际测试比例是各类比例的汇总,可能与入参略有偏差

参见:basalt.ml.DataSplit.Holdout, basalt.ml.DataSplit.Fold, basalt.ml.Estimators

方法

holdout(Matrix features, double[] targets, double testFraction, long seed) → Holdoutstatic

按比例切出一份测试集,其余作为训练集。

洗牌后取前 testSize 行为测试集,其余行为训练集,因此测试集在原始数据中并不连续。

注意

实际测试行数被夹到 [1, rows-1],样本极少时也不会产生空的一侧

参数
  • features (Matrix) – 样本矩阵,行数即样本数

  • targets (double[]) – 目标数组,长度必须等于 features.rows()

  • testFraction (double) – 测试集比例,必须落在开区间 (0, 1)

  • seed (long) – 洗牌随机源种子,决定具体划分

返回

持有 trainFeatures、trainTargets、testFeatures、testTargets 四个副本的 Holdout

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – targets 长度与行数不符、数据含 NaN/无穷,或 testFraction 不在 (0, 1)

trainTestSplit(Matrix features, double[] targets, double testFraction, long seed) → Holdoutstatic

按比例切分训练集与测试集,默认洗牌且不分层。

等价于 trainTestSplit(features, targets, testFraction, true, false, seed),也是 holdout 的实现。

参数
  • features (Matrix) – 样本矩阵,行数即样本数

  • targets (double[]) – 目标数组,长度必须等于 features 的行数

  • testFraction (double) – 测试集比例,必须落在开区间 (0, 1)

  • seed (long) – 洗牌随机源种子,决定具体划分

返回

持有 trainFeatures、trainTargets、testFeatures、testTargets 四个副本的 Holdout

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – targets 长度与行数不符、数据含非有限值、testFraction 不在 (0, 1),或样本数小于 2

trainTestSplit(Matrix features, double[] targets, double testFraction, boolean shuffle, boolean stratify, long seed) → Holdoutstatic

可控洗牌与分层的 holdout 切分。

不分层时先按 shuffle 决定是否对行下标做 Fisher-Yates 重排,取重排后的前 round(rows·testFraction) 行(夹到 [1, rows−1])作测试集,其余作训练集。

stratify 为真时改为按目标值分组:每组内部单独洗牌,按自身比例切出测试行且至少保留 1 行训练、1 行测试;只有单个样本的类整类留在训练集。因此实际测试比例是各类比例的汇总,可能与 testFraction 略有偏差。

注意

行数校验在分层判断之前,分层分支同样要求样本数不小于 2

注意

分层模式不重新混排类别,训练集与测试集内部按类别首次出现的顺序分块

注意

shuffle 为假时保持原始行序,此时测试集就是原始数据的头部若干行

参数
  • features (Matrix) – 样本矩阵,行数即样本数

  • targets (double[]) – 目标数组,长度必须等于 features 的行数;stratify 为真时按其中的取值分组

  • testFraction (double) – 测试集比例,必须落在开区间 (0, 1)

  • shuffle (boolean) – 为真时对行下标(分层时为每个类内的行号)做 Fisher-Yates 重排

  • stratify (boolean) – 为真时按目标值分组抽样,使训练集与测试集都保留全部类别

  • seed (long) – 洗牌随机源种子;不分层与分层两条分支各自新建 Random,含义相同

返回

四个字段均为新建副本的 Holdout

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – targets 长度与行数不符、数据含非有限值、testFraction 不在 (0, 1),或样本数小于 2

kFold(Matrix features, double[] targets, int folds, long seed) → List<Fold>static

按折数切分为互不重叠的测试块。

第 i 折的测试区间为 [i*rows/folds, (i+1)*rows/folds),训练集由其余折按洗牌顺序拼接而成,因此各折训练集大小同样只相差至多 1。

注意

列表顺序即折编号顺序,可直接顺序遍历做交叉验证

参数
  • features (Matrix) – 样本矩阵

  • targets (double[]) – 目标数组,长度必须等于 features.rows()

  • folds (int) – 折数,必须满足 2 <= folds <= features.rows()

  • seed (long) – 洗牌随机源种子

返回

长度为 folds 的 Fold 列表,测试块并集覆盖全部行

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – folds 越界,或 targets 长度不符、数据含非有限值

kFold(Matrix features, double[] targets, int folds, boolean shuffle, long seed) → List<Fold>static

按折数切分,可选是否先洗牌。

shuffle 为假时直接按原始行顺序切片,各折测试块是连续的原始区间;为真时先对行下标做 Fisher-Yates 重排,再在重排顺序上切段。

注意

训练集由测试块之前与之后两段拼接而成,行序与原始顺序不同

参数
  • features (Matrix) – 样本矩阵

  • targets (double[]) – 目标数组,长度必须等于 features 的行数

  • folds (int) – 折数,必须满足 2 <= folds <= 行数

  • shuffle (boolean) – 为真时先重排行下标,为假时保持原始顺序

  • seed (long) – 洗牌随机源种子;shuffle 为假时不起作用

返回

长度为 folds 的 Fold 列表,测试块并集覆盖全部行

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – folds 越界,或 targets 长度不符、数据含非有限值

stratifiedKFold(Matrix features, double[] targets, int folds, boolean shuffle, long seed) → List<Fold>static

按类别分层切分的 k 折。

先按目标值把行分组,每组内部可选洗牌,再用一个跨组连续累加的轮转计数器把样本依次放进 folds 个桶,因此同一类在各折的数量相差不超过 1。第 f 折以桶 f 为测试集,其余桶按桶序号拼接为训练集,每折都含有全部类别。

注意

轮转计数器跨类别连续累加,因此各类别的起始折不同

注意

只保证类内均衡,不保证各折总样本数完全相等

参数
  • features (Matrix) – 样本矩阵

  • targets (double[]) – 目标数组,长度必须等于 features 的行数;每个不同取值视为一个类别

  • folds (int) – 折数,必须满足 2 <= folds <= 行数,且每个类别的样本数不少于 folds

  • shuffle (boolean) – 为真时在每个类别内部做 Fisher-Yates 重排

  • seed (long) – 洗牌随机源种子;shuffle 为假时不起作用

返回

长度为 folds 的 Fold 列表,各折测试桶互不重叠且并集覆盖全部行

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – folds 越界、某个类别的样本数少于 folds,或 targets 长度不符、数据含非有限值

final class DecisionTree implements Estimator, Persistable

预分箱特征上的 CART 树,分裂搜索走直方图

分裂搜索基于直方图:一次遍历节点样本即可填满每个特征的类别计数(分类)或和与平方和(回归),随后每个桶边界以 O(classes) 或 O(1) 评估增益。分类准则为 GINI 或 ENTROPY,回归固定使用 MSE 的和与平方和等价形式。

叶子值:分类取多数类标签(票数相同时取下标最小者),回归取样本均值。特征重要性按「分裂增益乘以节点样本数」逐特征累加,再归一化到总和 1。

拟合结果展平为 TreeModel,推理只在原始数组上迭代行走。RandomForest 复用一份全局 BinnedFeatures 并调用 fitBinned 传入自助采样行号,省去每棵树的重复分箱与矩阵复制。

示例
Matrix x = Matrix.fromRows(new double[][]{
        {0.0, 1.0},
        {1.0, 1.0},
        {1.0, 0.0},
        {2.0, 0.0}});
double[] y = {0.0, 0.0, 1.0, 1.0};

DecisionTree tree = DecisionTree.builder()
        .task(TreeTask.CLASSIFICATION)
        .criterion(ImpurityCriterion.GINI)
        .maxDepth(3)
        .minSamplesLeaf(1)
        .bins(32)
        .seed(7L)
        .build()
        .fit(x, y);

double[] predicted = tree.predict(x);
double[] importance = tree.featureImportances();

注意

分裂要求两侧样本数均不小于 minSamplesLeaf,父节点样本数不小于 minSamplesSplit 与 2*minSamplesLeaf

注意

最优增益不超过 1e-12*max(1, 父不纯度) 时停止分裂,节点转为叶

注意

maxDepth 为 0 时根节点直接成为叶

注意

fit 就地更新估计器状态并返回 this

参见:basalt.ml.RandomForest, basalt.ml.TreeModel, basalt.ml.ImpurityCriterion

方法

builder() → Builderstatic

创建构造器,参数全部取默认值

返回

新的 Builder 实例

fit(Matrix features, double[] targets) → DecisionTree

在原始特征矩阵上分箱并训练单棵树

先校验训练数据,再以 maxBins 构建 BinnedFeatures,最后用全部行号调用 fitBinned。分类标签按升序去重后编码为 0 起的整数,回归直接使用原始目标值。

注意

每次调用都会重建分箱与树,重复拟合覆盖上一次结果

参数
  • features (Matrix) – 训练特征矩阵,行数为样本数,列数成为特征数

  • targets (double[]) – 目标数组,长度必须等于行数;分类为类别标签,回归为连续值

返回

this,已完成拟合

抛出
  • IllegalArgumentException – 目标数量与行数不一致、特征或目标含非有限值,或样本数小于 minSamplesLeaf

  • NullPointerException – features 或 targets 为 null

predict(Matrix features) → double[]

输出每行的叶值,分类为类别标签

内部调用 TreeModel.addInto 一次遍历完成,不做逐行对象分配。分类返回叶节点保存的类别标签,回归返回叶节点均值。

参数
  • features (Matrix) – 特征矩阵,列数须等于拟合时的特征数

返回

长度为行数的预测数组

抛出
  • IllegalStateException – 估计器尚未拟合

  • IllegalArgumentException – 列数与拟合时不一致,或含非有限值

featureImportances() → double[]

归一化的特征重要性,总和为 1

口径为「分裂增益乘以该节点样本数」,在整棵树范围内按特征累加;总和大于 0 时整体除以总和,否则保持全零。只有真正参与分裂的特征会累积到非零值。

注意

返回 clone,修改不影响估计器内部状态

返回

长度为特征数的副本;树未产生分裂时全为 0

抛出
  • IllegalStateException – 估计器尚未拟合

task() → TreeTask

构造时指定的任务类型

返回

CLASSIFICATION 或 REGRESSION

classes() → double[]

分类任务的类别标签,按升序排列

注意

标签顺序来自 TreeMap 的自然序,与 predictProbability 的列顺序无关

返回

类别标签副本;回归任务返回 null

featureCount() → int

拟合时使用的特征数

返回

特征数;未拟合为 0

nodeCount() → int

树的节点总数

返回

节点数,含叶节点;未拟合为 0

depth() → int

根到叶的最大边数

返回

树深;未拟合或单叶树为 0

kind() → ModelKind

返回模型类型标识。

返回

ModelKind.DECISION_TREE

write(ModelWriter writer)

序列化入口,等价于 writeState。

Persistable 的实现方法,直接委托 writeState,落盘格式与直接调用 writeState 完全一致。

注意

读取端用静态 read 或 readState 均可,两者等价

参数
  • writer (ModelWriter) – 目标写入器,由调用方负责容器头与关闭

抛出
  • IllegalStateException – 估计器尚未拟合

read(ModelReader reader) → DecisionTreestatic

反序列化入口,等价于 readState。

静态工厂,直接委托 readState;读回后超参数取 Builder 默认值,只有任务、类别标签与树拓扑被还原。

注意

静态方法,调用形式为 DecisionTree.read(reader)

参数
  • reader (ModelReader) – 已定位到本对象载荷起点的读取器

返回

新的 DecisionTree 实例,已具备预测能力

抛出
  • ModelFormatException – 任务序号越界,或分类树缺少类别标签

writeState(ModelWriter writer)

写出特征数、任务、类别标签与树拓扑

写入顺序为特征数、任务序号、类别数(回归写 0)与类别标签,最后是树的节点数组。超参数不落盘,读取方需要自行重建配置;分类树缺少标签会导致读取失败。

注意

与 readState 成对使用,格式由 ModelCodec 的容器包裹

参数
  • writer (ModelWriter) – 目标二进制写入器

抛出
  • IllegalStateException – 估计器尚未拟合

readState(ModelReader reader) → DecisionTreestatic

从二进制流重建树

注意

重建后的超参数取 Builder 默认值,仅任务与准则被还原

注意

重建后的特征重要性全为 0,不参与持久化

参数
  • reader (ModelReader) – 已定位到本对象载荷起点的读取器

返回

新的 DecisionTree 实例,已具备预测能力

抛出
  • ModelFormatException – 任务序号越界,或分类树缺少类别标签

enum DistanceMetric

KNN 使用的距离函数枚举。

EUCLIDEAN 返回平方欧氏距离开方,MANHATTAN 返回逐元素绝对差之和;两者都调用 VectorMath 的 SIMD 内核,按扁平数组上的偏移窗口计算。

distance 直接接收两个 double[] 与起始偏移,因此可以在 Matrix.data() 上按行取窗口,不必为每一行构造临时数组。

示例
double[] a = {1.0, 2.0, 3.0};
double[] b = {1.0, 4.0, 3.0};
double euclidean = DistanceMetric.EUCLIDEAN.distance(a, 0, b, 0, 3);
double manhattan = DistanceMetric.MANHATTAN.distance(a, 0, b, 0, 3);

注意

偏移以元素为单位,不是字节

注意

不做越界检查,调用方需保证 offset + length 不超出数组长度

注意

两个常量都在枚举体内覆写 distance,没有默认实现

参见:basalt.ml.KNearestNeighbors, basalt.ml.KNeighborsRegressor

方法

distance(double[] a, int aOffset, double[] b, int bOffset, int length) → doubleabstract

计算两段等长向量在该度量下的距离。

注意

越界与 length 为负都不检查,由调用方保证

参数
  • a (double[]) – 第一个向量的扁平存储

  • aOffset (int) – a 中参与计算的起始元素下标

  • b (double[]) – 第二个向量的扁平存储

  • bOffset (int) – b 中参与计算的起始元素下标

  • length (int) – 参与计算的元素个数,即特征维数

返回

按枚举常量定义的距离,非负;相同位置返回 0.0

enum EigenSolver

PCA 可选的对称特征分解求解器。

AUTO 依据数据形状挑选实现:特征数大于样本数时走 GRAM,否则走 JACOBI。JACOBI 直接分解 p × p 协方差矩阵,GRAM 分解 n × n Gram 矩阵再还原主方向。

显式指定的求解器不会因形状被改写;但 GRAM 需要为 n × n 矩阵分配内存,样本数超过 20000 时 fit 拒绝执行。

注意

AUTO 仅在特征数大于样本数且样本数不超过 20000 时选择 GRAM

注意

两条路径输出在符号与数值误差范围内一致,符号由最大绝对值分量为正的约定固定

参见:basalt.ml.PCA, basalt.ml.PCA.Builder

枚举成员

AUTO()

特征数多于样本数时选 GRAM,否则选 JACOBI

JACOBI()

对 p×p 协方差做 Jacobi 对角化,O(n·p²)

GRAM()

对 n×n Gram 矩阵做对角化,适合宽表,O(n²·p)

interface Estimator

经典估计器的统一契约。

fit 消费特征矩阵与目标数组,就地更新估计器状态并返回 this,便于链式调用;predict 返回与输入行数等长的预测数组,顺序与输入行一一对应。

接口不规定重复 fit 的语义、也不声明线程安全:实现类在 fit 期间可变,predict 只读,因此同一实例的并发 predict 依赖实现是否持有可变临时状态。无监督实现可忽略 targets。

示例
Matrix x = Matrix.fromRows(new double[][]{{0, 0}, {0, 1}, {1, 0}, {1, 1}});
double[] y = {0, 1, 1, 0};
Estimator model = KNearestNeighbors.builder().k(3).build().fit(x, y);
double[] prediction = model.predict(x);

注意

predict 前必须先 fit,实现类通过内部标记抛出 IllegalStateException

注意

不同实现的 predict 返回语义不同:分类器返回原始类别标签,回归器返回连续值

参见:basalt.ml.Estimators, basalt.ml.Metrics

final class Estimators

按枚举选择算法的一行式门面。

fit 按 Algorithm 分支构造对应估计器并立即训练,超参数一律取各 Builder 的默认值;需要调参时改用具体类的 builder()。有监督算法传入 null targets 会被拒绝,无监督算法则忽略 targets 并以 null 调用。

crossValidate 用 DataSplit.kFold 做种子固定为 42 的 k 折划分,逐折训练、预测、计分,返回各折算术平均。RMSE 在累加前取负号,使所有 Metric 都满足越大越好。

示例
Matrix x = Matrix.fromRows(new double[][]{{0, 0}, {0, 1}, {1, 0}, {1, 1}, {2, 2}, {2, 1}});
double[] y = {0.5, 1.0, 1.5, 2.0, 2.5, 2.2};
Estimator model = Basalt.fit(Basalt.Algorithm.RIDGE, x, y);
double[] prediction = Basalt.predict(model, x);
double score = Basalt.crossValidate(Basalt.Algorithm.RIDGE, x, y, 3, Estimators.Metric.R2);

注意

门面不缓存模型也不管理生命周期,返回的 Estimator 由调用方持有

注意

交叉验证的划分种子固定为 42,相同输入的结果可复现

注意

folds 的合法范围沿用 DataSplit.kFold 的约束(2 到样本数)

注意

门面本身无状态,全部方法为 static

参见:basalt.ml.Estimators.Algorithm, basalt.ml.Estimators.Metric, basalt.ml.Estimator, basalt.ml.DataSplit

方法

fit(Algorithm algorithm, Matrix features, double[] targets) → Estimatorstatic

按算法枚举训练一个默认配置的估计器。

分支覆盖 16 个算法常量,其中 RANDOM_FOREST_REGRESSOR 复用 RandomForest 并切换 task,两个梯度提升常量分别绑定 LOGISTIC 与 SQUARED_ERROR 目标。

注意

KNN 与 KNN_REGRESSOR 固定 k=5、欧氏距离

注意

KMEANS、PCA 调用只接收特征的 fit 重载;DBSCAN 以 null targets 调用 fit

参数
  • algorithm (Algorithm) – 算法枚举,同时决定实现类与默认超参数

  • features (Matrix) – 训练特征矩阵

  • targets (double[]) – 训练目标;有监督算法不可为 null

返回

已拟合的估计器实例,静态类型为 Estimator

抛出
  • NullPointerException – algorithm 为 null

  • IllegalArgumentException – 有监督算法传入 null targets,或训练数据未通过估计器自身的校验

predict(Estimator model, Matrix features) → double[]static

委托给估计器自身的 predict。

注意

门面不追加任何校验,全部检查由估计器完成

参数
  • model (Estimator) – 已拟合的估计器

  • features (Matrix) – 待预测特征矩阵

返回

估计器返回的预测数组,不做转换

抛出
  • NullPointerException – model 为 null

  • IllegalStateException – model 尚未 fit

crossValidate(Algorithm algorithm, Matrix features, double[] targets, int folds, Metric metric) → doublestatic

k 折交叉验证并返回各折指标均值。

每折独立调用 fit 重新训练,模型之间不共享状态;指标在折内测试集上计算后累加,最后除以折数。

注意

划分种子固定为 42,重复调用结果一致

注意

ACCURACY 与 MACRO_F1 要求预测是类别码,R2 与 RMSE 要求连续值,错配不报错

参数
  • algorithm (Algorithm) – 待评估算法,必须是有监督算法

  • features (Matrix) – 全部样本特征

  • targets (double[]) – 全部样本目标,长度等于特征行数

  • folds (int) – 折数,2 <= folds <= 样本数

  • metric (Metric) – 评估指标枚举

返回

各折指标的算术平均;RMSE 以负值参与平均,故越大越好

抛出
  • IllegalArgumentException – 算法属于 UNSUPERVISED,或 folds 越界、数据校验失败

final class FeatureImportance

统一的特征重要性入口:树杂质、线性权重绝对值与置换重要性。

三种口径按模型分派。树的杂质重要性直接复用 DecisionTree、RandomForest、HistogramGradientBoosting 的 featureImportances,量纲是「分裂增益乘以节点样本数」,本身已归一化到总和 1;线性模型取权重绝对值后归一化,反映的是系数幅度,方向信息因此丢失,也不代表对预测的因果贡献。

置换重要性不依赖模型内部结构:以真实目标与未打乱预测算出的分数为基线,逐列打乱该特征后重新预测,用分数下降量衡量重要性。它对任意 Estimator 与 Pipeline 都成立,也能反映特征间的交互,代价是每列 nRepeats 次完整预测。

of 遇到 Pipeline 会递归到 p.estimator(),返回的是末端估计器所见特征空间的重要性,列数可能不等于原始输入列数。

示例
Matrix x = Matrix.fromRows(new double[][]{
        {0.0, 1.0}, {1.0, 1.0}, {1.0, 0.0}, {2.0, 0.0}});
double[] y = {0.0, 0.0, 1.0, 1.0};
DecisionTree tree = DecisionTree.builder()
        .task(TreeTask.CLASSIFICATION)
        .maxDepth(3)
        .build()
        .fit(x, y);

double[] impurity = FeatureImportance.of(tree);
FeatureImportance.PermutationResult permuted = FeatureImportance.permutationImportance(
        tree, x, y, Estimators.Metric.ACCURACY, 5, 42L);
double[] mean = permuted.importancesMean();
int[] order = permuted.rankedFeaturesDescending();

注意

of 只支持 DecisionTree、RandomForest、HistogramGradientBoosting、Ridge、Lasso、LinearRegression、LogisticRegression、LinearSVM,其余类型抛 IllegalArgumentException

注意

线性归一化把绝对值之和缩放到 1;系数全为零时保持全零而不做除法

注意

置换重要性返回分数下降量,正值表示该特征有用,负值表示打乱后反而更好(常见于噪声列)

注意

metric 已统一为越大越好(RMSE 在内部取负),因此误差指标下「置换后变差」同样得到正的重要性

注意

置换在特征矩阵副本上进行,不会修改调用方传入的矩阵

参见:basalt.ml.DecisionTree, basalt.ml.RandomForest, basalt.ml.HistogramGradientBoosting

方法

of(Estimator model) → double[]static

返回归一化到总和 1 的固有特征重要性。

按类型分派取原始值:树模型用其 featureImportances,线性模型用权重绝对值;随后整体除以总和,使结果之和为 1。Pipeline 会先递归到底层估计器。

注意

返回的数组可安全修改,树实现内部返回 clone

注意

对 Pipeline 只取末端估计器,忽略前置变换对列的影响

参数
  • model (Estimator) – 已拟合的估计器;未拟合的树在取重要性时抛 IllegalStateException

返回

长度等于该估计器特征数的数组,非负且总和为 1;原始值全零时保持全零

抛出
  • NullPointerException – model 为 null

  • IllegalArgumentException – 该估计器类型不暴露固有重要性

permutationImportance(Estimator model, Matrix features, double[] targets, Estimators.Metric metric, int nRepeats, long seed) → PermutationResultstatic

逐列打乱特征,用评分下降量衡量重要性。

先对未打乱的预测算基线分数;再对每一列重复 nRepeats 次:用同一个 Random 做 Fisher-Yates 重排行下标,按重排结果把该列的值搬到新位置,复制成新矩阵后重新预测,单次下降量 = 基线 − 打乱后分数。最后按列求均值,并以总体标准差(除以 nRepeats)作为波动量。

注意

rawImportances 形状为 特征数 × nRepeats,第 c 行是第 c 列的各次下降量

注意

行下标数组在所有列与所有重复之间复用,洗牌状态不重置

注意

结果用 PermutationResult.rankedFeaturesDescending 可直接取降序特征下标

参数
  • model (Estimator) – 已拟合的估计器;predict 会被调用 列数×nRepeats+1 次

  • features (Matrix) – 评估用样本矩阵,行数为样本数、列数为特征数;元素必须有限

  • targets (double[]) – 真实目标,长度必须等于 features 的行数

  • metric (Estimators.Metric) – 评分口径,取 Estimators.Metric 的 ACCURACY、MACRO_F1、R2 或 RMSE;RMSE 在内部取负,使所有指标都越大越好

  • nRepeats (int) – 每列重复打乱的次数,必须为正

  • seed (long) – 洗牌随机源种子,决定重排序列

返回

持有 importancesMean、importancesStd 与 rawImportances 的 PermutationResult

抛出
  • NullPointerException – model、features、targets 或 metric 为 null

  • IllegalArgumentException – 目标数与行数不符、数据含非有限值,或 nRepeats 不为正

  • IllegalStateException – model 尚未拟合

final class GaussianMixture implements Estimator, Persistable

EM 估计的高斯混合模型,协方差可选 FULL / TIED / DIAG。

协方差由 covarianceType 决定:FULL 为每个分量存一个 p×p 矩阵,TIED 让全部分量共享一个矩阵,DIAG 只存 p 个方差。FULL 与 TIED 在每轮 E 步前先做 Cholesky 分解,用前代把马氏距离换成 ‖L⁻¹(x−μ)‖²,对数行列式取 2·Σlog L_ii;分解失败时按 regCovar·10ⁿ 追加 jitter 重试,6 次仍非正定则抛 IllegalStateException。

拟合先用 KMeans 初始化:簇数等于 components、maxIterations 固定 30、使用同一 seed。均值取质心,权重取簇占比,协方差取簇内样本协方差(TIED 取全局共享)。随后每轮 E 步计算「log 权重 + 对数密度」并按行做 log-sum-exp 得到责任度,M 步更新权重、均值与协方差,相邻两轮平均对数似然差不超过 tolerance 即收敛。

AIC/BIC 的自由参数个数随协方差类型变化:DIAG 为 K·2p+K−1,FULL 为 K·(p+p(p+1)/2)+K−1,TIED 为 K·p+p(p+1)/2+K−1。相关特征上 FULL 的对数似然明显更高,但参数更多,需用 AIC/BIC 权衡。

注意

默认 covarianceType 为 FULL;改回 DIAG 可获得 O(K·p) 的存储与求值,代价是无法表达分量内的特征相关

注意

E 步对权重取 max(1e-15, w) 后再取对数,某个分量被压到 0 时不会出现负无穷

注意

lowerBound 是平均每样本对数似然而非总似然,量纲与 sklearn 的 lower_bound_ 一致

注意

write 落盘协方差类型与完整 p×p 矩阵;read 之后 maxIterations、tolerance、regCovar、seed 回落到 Builder 默认值

注意

DIAG 的非对角项恒为 0,但 covariance(k) 仍返回 p×p 稠密矩阵,便于统一处理

方法

builder() → Builderstatic

创建 GaussianMixture 构建器。

返回

components 为 2、maxIterations 为 100、tolerance 为 1e-4、regCovar 为 1e-6、seed 为 42 的新 Builder 实例

fit(Matrix features) → GaussianMixture

以无监督方式拟合混合模型。

等价于 fit(features, null),目标数组不参与计算。

参数
  • features (Matrix) – 样本矩阵,行是样本、列是特征;元素必须有限

返回

this,便于链式调用

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – features 含非有限值,或 components 大于样本数

fit(Matrix features, double[] ignoredTargets) → GaussianMixture

用 EM 估计混合权重、均值与方差。

初始化阶段调用 KMeans 得到质心与初始簇划分,据此估算各分量的初始方差与权重;之后交替执行 E 步(算责任度、算 lowerBound)与 M 步(用责任度加权重估权重、均值、方差,并把 regCovar 加回方差)。

注意

每轮 E 步都覆盖 lowerBound,未收敛时它对应最后一次 E 步

注意

M 步用 max(nk, 1e-10) 作分母,空分量的权重被压到接近 0 而不会除零

参数
  • features (Matrix) – 样本矩阵,行数为样本数,列数成为特征数;元素必须有限

  • ignoredTargets (double[]) – 占位参数;混合模型为无监督任务,源码不读取,传 null 或任意数组均可

返回

this,已完成拟合

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – features 含非有限值,或 components 大于样本数

scoreSamples(Matrix features) → double[]

返回每个样本的对数概率密度 log p(x)。

逐样本对 K 项的「log 权重 + 对角高斯对数密度」做 log-sum-exp:先减最大值,再取指数累加取对数,最后加回最大值,避免下溢。

参数
  • features (Matrix) – 样本矩阵,列数须等于拟合时的特征数;元素必须有限

返回

长度为样本数的对数密度数组,元素通常为负

抛出
  • NullPointerException – features 为 null

  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 特征列数与拟合时不一致,或含非有限值

predictProbability(Matrix features) → Matrix

返回样本属于各分量的后验概率。

对每行做减最大值的 softmax,得到 K 个非负且和为 1 的责任度,等价于 E 步的输出。

参数
  • features (Matrix) – 样本矩阵,列数须等于拟合时的特征数;元素必须有限

返回

样本数 × components 的矩阵,第 k 列对应第 k 个分量

抛出
  • NullPointerException – features 为 null

  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 特征列数与拟合时不一致,或含非有限值

predict(Matrix features) → double[]

返回后验概率最大的分量编号。

先算后验概率矩阵,再逐行取最大列。比较用严格大于,概率并列时返回编号较小的分量。

参数
  • features (Matrix) – 样本矩阵,列数须等于拟合时的特征数;元素必须有限

返回

长度为样本数的分量编号数组,取值 0 到 components−1

抛出
  • NullPointerException – features 为 null

  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 特征列数与拟合时不一致,或含非有限值

parameterCount() → int

按协方差类型计算的自由参数个数

返回

DIAG 为 K·2p+K−1,FULL 为 K·(p+p(p+1)/2)+K−1,TIED 为 K·p+p(p+1)/2+K−1

aic(Matrix features) → double

赤池信息量,用于在分量数之间取舍。

logLik 取 scoreSamples 之和,nParams = components·2·特征数 + (components−1),返回 2·nParams − 2·logLik。参数越多惩罚越大,似然越高值越小。

注意

参数计数按对角协方差给出,每个分量计 p 个均值与 p 个方差

注意

样本数不影响 AIC,只影响 logLik 的累加项数

参数
  • features (Matrix) – 用于评估的样本矩阵,列数须与拟合时一致,可与训练集不同

返回

AIC 值,无下界

抛出
  • NullPointerException – features 为 null

  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 特征列数与拟合时不一致,或含非有限值

bic(Matrix features) → double

贝叶斯信息量,对参数的惩罚随样本数增长。

返回 nParams·ln(rows) − 2·logLik,nParams 与 aic 相同,rows 为传入矩阵的行数。样本数超过 e² 时 ln(rows) 大于 2,同一模型的 BIC 惩罚重于 AIC,因此 BIC 更倾向少分量。

注意

样本数取自传入矩阵而非训练集,用测试集评估时惩罚项随之变化

参数
  • features (Matrix) – 用于评估的样本矩阵,列数须与拟合时一致,可与训练集不同

返回

BIC 值,无下界

抛出
  • NullPointerException – features 为 null

  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 特征列数与拟合时不一致,或含非有限值

weights() → double[]

返回各分量的混合权重。

权重由 M 步的 nk/rows 得到,总和为 1;未经过 M 步时是初始化阶段的类频率。

返回

长度等于 components 的副本;未拟合时返回 null 而不抛异常

covarianceType() → CovarianceType

拟合时使用的协方差参数化

返回

FULL、TIED 或 DIAG

means() → Matrix

返回各分量的均值向量。

返回

components × 特征数 的矩阵,第 k 行是第 k 个分量的均值

抛出
  • IllegalStateException – 尚未拟合

variances() → Matrix

返回各分量的对角方差。

矩阵元素已包含 regCovar,因此均不小于 regCovar,可直接用于高斯密度求值。

注意

只保存对角元素,非对角协方差不在模型中

返回

components × 特征数 的矩阵,第 k 行是第 k 个分量在各特征上的方差

抛出
  • IllegalStateException – 尚未拟合

covariance(int component) → Matrix

返回某个分量的 p×p 协方差矩阵

参数
  • component (int) – 分量下标,需满足 0 ≤ component < components

返回

形状 [featureCount, featureCount] 的稠密对称矩阵;DIAG 时非对角为 0

抛出
  • IllegalArgumentException – component 越界

  • IllegalStateException – 模型尚未拟合

converged() → boolean

报告 EM 是否在迭代上限内达到收敛判据。

返回

收敛为 true;未拟合或跑满 maxIterations 仍不满足为 false

iterations() → int

返回实际执行的 EM 轮数。

注意

收敛的那一轮也计入,即使该轮跳过了 M 步

返回

轮数,从 1 开始计;未拟合为 0,未收敛时等于 maxIterations

lowerBound() → double

返回最近一轮的平均每样本对数似然。

每轮 E 步把它更新为 totalLogProb/rows,因此它是收敛判据的比较对象,也是逐轮单调不减的见证量。

注意

收敛时对应最后一次 E 步,而非最后一次 M 步的参数

返回

lowerBound 值;未拟合时为 0.0

kind() → ModelKind

返回模型类型标识。

返回

ModelKind.GAUSSIAN_MIXTURE

write(ModelWriter writer)

把超参数与全部统计量写入序列化流。

写入顺序为 components、特征数、收敛标志、迭代轮数、lowerBound、权重、均值、方差。maxIterations、tolerance、regCovar、seed 不落盘。

注意

与静态 read 成对使用,读取端必须按同一顺序消费

参数
  • writer (ModelWriter) – 目标写入器,由调用方负责容器头与关闭

抛出
  • IllegalStateException – 尚未拟合

read(ModelReader reader) → GaussianMixturestatic

从序列化流重建 GaussianMixture。

注意

静态方法,调用形式为 GaussianMixture.read(reader)

注意

读回的 converged、iterations、lowerBound 来自流,不重新计算

参数
  • reader (ModelReader) – 已完成容器头解析的读取器

返回

恢复统计量的新实例,超参数取 Builder 默认值

抛出
  • ModelFormatException – components 或特征数不为正

final class GaussianNaiveBayes implements Estimator, Persistable

按类估计均值、方差与先验的高斯朴素贝叶斯分类器。

拟合时按目标值升序枚举类别,逐类计算各特征均值与总体方差(除以该类样本数),先验取类频率的对数。预测在对数域累加先验与各特征的独立高斯对数似然,避免概率连乘下溢。

方差平滑沿用 scikit-learn 的尺度无关约定:epsilon 等于 varianceSmoothing 乘以全体方差最大值,再加到每个方差上;该乘积不为正时直接使用 varianceSmoothing。

示例
Matrix features = Matrix.fromRows(new double[][] {
    {1.0, 2.0}, {1.2, 1.8}, {0.9, 2.1},
    {5.0, 8.0}, {5.4, 7.6}, {4.8, 8.2}
});
double[] targets = {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
GaussianNaiveBayes model = GaussianNaiveBayes.builder()
        .varianceSmoothing(1e-9)
        .build()
        .fit(features, targets);
double[] predicted = model.predict(features);
Matrix logPosterior = model.predictLogProbability(features);
Matrix posterior = model.predictProbability(features);

注意

类别取值按升序排列,概率并列时 predict 返回序号最小、即取值最小的类

注意

拟合样本数不少于 512 且原生内核可用时由原生实现计算均值、方差与先验

注意

varianceSmoothing 不写入序列化流,read 后取 Builder 默认值;已平滑的方差本身被保存,预测不受影响

参见:basalt.ml.Estimator, basalt.core.Persistable

方法

builder() → Builderstatic

创建 GaussianNaiveBayes 构建器。

返回

参数取默认值的新 Builder 实例

fit(Matrix features, double[] targets) → GaussianNaiveBayes

估计各类的均值、方差与先验。

类别集合来自目标数组的去重升序结果,随后两遍扫描:第一遍累计类内和与类计数得到均值、先验,第二遍累计离差平方得到总体方差,最后统一加上平滑项 epsilon。

参数
  • features (Matrix) – 训练样本矩阵,行是样本、列是特征;元素必须有限

  • targets (double[]) – 每行对应的类别标签,长度必须等于样本数;元素必须有限

返回

this,便于链式调用

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – targets 长度与样本数不一致,或存在非有限值

predictLogProbability(Matrix features) → Matrix

返回各类的对数联合概率矩阵。

每个元素等于 log(先验) 加上各特征对数高斯密度之和,形如 -0.5 · (log(2πσ²) + (x - μ)² / σ²) 的累加。数值上比直接乘概率稳定。

参数
  • features (Matrix) – 样本矩阵,列数须与拟合时一致

返回

样本数 × 类别数 的矩阵,列顺序与 classes() 一致

抛出
  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 特征列数与拟合时不一致

predictProbability(Matrix features) → Matrix

把对数联合概率归一化为后验概率。

逐行减去最大值后取指数并归一,等价于对对数概率做 softmax,可避免上溢。若整行对数概率都不是有限值,则退化为按先验归一;先验之和也不为正时返回均匀分布。

参数
  • features (Matrix) – 样本矩阵,列数须与拟合时一致

返回

样本数 × 类别数 的矩阵,每行元素和为 1

抛出
  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 特征列数与拟合时不一致

predict(Matrix features) → double[]

返回后验概率最大的类别标签。

先计算后验概率矩阵,再逐行取最大列,映射回原始类别取值。比较使用严格大于,因此概率并列时返回序号最小、即取值最小的类。

参数
  • features (Matrix) – 样本矩阵,列数须与拟合时一致

返回

长度为样本数的类别标签数组

抛出
  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 特征列数与拟合时不一致

classes() → double[]

返回按升序排列的类别取值。

返回

类别数组的副本;未拟合时为 null

means() → Matrix

返回各类别各特征的均值矩阵。

返回

类别数 × 特征数 的矩阵,第 i 行对应 classes()[i]

抛出
  • IllegalStateException – 尚未拟合

variances() → Matrix

返回各类别各特征的方差矩阵。

数值为总体方差(分母是类内样本数)加平滑项 epsilon 之后的结果,因此全部为正,不会出现零方差导致除零。

返回

类别数 × 特征数 的矩阵,第 i 行对应 classes()[i]

抛出
  • IllegalStateException – 尚未拟合

logPriors() → double[]

返回各类别先验概率的自然对数。

注意

取对数而非概率,便于与对数似然直接相加

返回

长度等于类别数的数组副本;未拟合时为 null

kind() → ModelKind

返回模型类型标识。

返回

ModelKind.GAUSSIAN_NAIVE_BAYES

write(ModelWriter writer)

把特征数、类别、均值、方差与对数先验写入序列化流。

注意

写入顺序为特征数、类别数、类别、均值、方差、对数先验,读取端必须按同一顺序消费

参数
  • writer (ModelWriter) – 目标写入器,由调用方负责容器头与关闭

抛出
  • IllegalStateException – 尚未拟合

read(ModelReader reader) → GaussianNaiveBayesstatic

从序列化流重建 GaussianNaiveBayes 模型。

参数
  • reader (ModelReader) – 已完成容器头解析的读取器

返回

只恢复统计量的模型实例,varianceSmoothing 取 Builder 默认值

抛出
  • ModelFormatException – 特征数或类别数不为正

final class GridSearchCV implements Estimator

网格穷举加交叉验证的调参器,选优后全量重训。

交叉验证来源是 DataSplit:stratified 为 false 时调用 DataSplit.kFold,为 true 时调用 DataSplit.stratifiedKFold,两者都以 shuffle=true 与构造时的 seed 打乱,折数为 cvFolds。

param 声明的每个键对应一组候选值,所有键做笛卡尔积并按声明顺序遍历。每个组合在每折上调用一次 estimatorFactory 新建估计器,在训练折拟合、测试折预测,再用 scoring 折算为标量:ACCURACY、MACRO_F1、R2 取原值,RMSE 取负值,因此分数一律越大越好。

组合之间用各折均值比较,严格大于才替换当前最优,并列时保留先出现的组合;均值标准差按总体公式 sqrt(Σ(s-mean)²/k) 计算。选优后以同一工厂再构造一个估计器并在全部数据上拟合,作为 bestEstimator。

示例
Matrix x = Matrix.fromRows(new double[][] {
        {0.0, 0.0}, {0.2, 0.1}, {0.1, 0.3}, {0.3, 0.2},
        {1.0, 1.0}, {1.2, 0.9}, {0.9, 1.1}, {1.1, 1.2}
});
double[] y = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0};

GridSearchCV search = GridSearchCV.builder(
                params -> KNearestNeighbors.builder()
                        .k((Integer) params.get("k"))
                        .build())
        .param("k", 1, 3)
        .scoring(Estimators.Metric.ACCURACY)
        .cv(2)
        .stratified(true)
        .seed(42L)
        .build()
        .fit(x, y);

Estimator best = search.bestEstimator();
Map<String, Object> bestParams = search.bestParams();
double bestScore = search.bestScore();
double[] label = search.predict(x);

注意

默认 scoring=ACCURACY、cvFolds=5、stratified=false、seed=42;构建时 paramGrid 为空会抛 IllegalArgumentException

注意

RMSE 评分下 bestScore 与 cvResults 中的分数均为负值,比较时仍取最大者

注意

分层划分要求每个类别的样本数不少于折数,否则 DataSplit 抛 IllegalArgumentException

注意

工厂每折调用一次,估计器实例不跨折复用,工厂内部应无共享可变状态

注意

每次 fit 会清空 cvResults 并重置最优结果

参见:basalt.ml.KFold, basalt.ml.DataSplit, basalt.ml.Estimators, basalt.ml.Estimator

方法

builder(Function<Map<String, Object>, Estimator> estimatorFactory) → Builderstatic

以估计器工厂创建构造器。

参数
  • estimatorFactory (Function<Map<String, Object>, Estimator>) – 参数组合到未拟合估计器的映射,每折调用一次且应返回新实例

返回

新的 Builder 实例,scoring=ACCURACY、cvFolds=5、stratified=false、seed=42

抛出
  • NullPointerException – estimatorFactory 为 null

fit(Matrix features, double[] targets) → GridSearchCV

按折评分遍历网格并重训最优模型。

先按 stratified 选择划分方式,以 cvFolds 与 seed 生成折;再对 param 网格取笛卡尔积,逐个组合在每折上新建估计器、拟合训练折、预测测试折并折算分数,得到均值与总体标准差。

比较用严格大于,并列时保留先出现的组合;结束后用最优参数在全部数据上重新拟合一次作为 bestEstimator。

注意

折数大于样本数时同样由 DataSplit 抛 IllegalArgumentException

注意

同一组合的各折互不影响,分数按折序存入 foldScores

参数
  • features (Matrix) – 训练特征矩阵,行数为样本数

  • targets (double[]) – 目标数组,长度须等于行数

返回

this,已完成拟合并持有最优估计器

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – 目标数量与行数不一致、数据含非有限值,或分层划分时某类样本数少于折数

predict(Matrix features) → double[]

用最优估计器预测。

注意

列数校验由最优估计器自身的 predict 完成

参数
  • features (Matrix) – 待预测特征矩阵,列数须与训练数据一致

返回

最优估计器的预测数组,标签或回归值取决于被调优的估计器

抛出
  • IllegalStateException – 尚未拟合

bestEstimator() → Estimator

返回在全部数据上重训的估计器。

返回

已完成拟合的 Estimator 实例

抛出
  • IllegalStateException – 尚未拟合

bestParams() → Map<String, Object>

返回最优参数组合。

返回

不可变的参数映射,键与 param 声明一致

抛出
  • IllegalStateException – 尚未拟合

bestScore() → double

返回最优组合的交叉验证均分。

返回

各折分数的算术平均;scoring 为 RMSE 时为负值

抛出
  • IllegalStateException – 尚未拟合

cvResults() → List<CandidateResult>

返回每个候选组合的逐折成绩。

注意

未拟合时返回空列表,不抛异常

注意

stdScore 为总体标准差,分母取折数而非折数减一

注意

fit 会清空并重建该列表

返回

不可变列表,元素为 CandidateResult(params、meanScore、stdScore、foldScores),顺序与网格遍历顺序一致

final class HistogramGradientBoosting implements Estimator, Persistable

二阶直方图梯度提升,支持深度优先与叶优先生长

分裂增益按正则化目标计算:0.5*(G_L^2/(H_L+lambda) + G_R^2/(H_R+lambda) - G^2/(H+lambda)) - gamma,叶权重为 -G/(H+lambda)。直方图用相减技巧:每次只累加较小子节点,较大子节点由 parent 减 small 得到,平衡树因此只做约一半遍历。

XGBOOST 策略按层递归,由 maxDepth 控制深度;LIGHTGBM 策略用优先队列每轮分裂全局增益最大的叶,由 maxLeaves 控制叶数。两种策略都受 minSamplesLeaf、minChildWeight 与 maxDepth 约束。

累计量较大时通过 JNI 交给 Rust AVX2 内核,原生调用失败则回退到分块并行的 Java 路径。featureFraction 按轮次抽取特征子集,validationFraction 切出验证集,配合 earlyStoppingRounds 把树列表回退到最优轮次。

示例
Matrix x = Matrix.fromRows(new double[][]{
        {0.0, 1.0}, {1.0, 1.0}, {1.0, 0.0}, {2.0, 0.0},
        {2.0, 1.0}, {3.0, 0.0}, {3.0, 1.0}, {4.0, 0.0}});
double[] y = {0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0};

HistogramGradientBoosting model = HistogramGradientBoosting.builder()
        .algorithm(BoostingAlgorithm.LIGHTGBM)
        .objective(BoostingObjective.LOGISTIC)
        .iterations(200)
        .learningRate(0.1)
        .maxLeaves(15)
        .featureFraction(0.8)
        .validationFraction(0.25)
        .earlyStoppingRounds(20)
        .build()
        .fit(x, y);

double[] probability = model.predictProbability(x);
double[] label = model.predict(x);
double[] history = model.lossHistory();

注意

LOGISTIC 目标要求标签恰为 0 或 1,其余取值在 fit 入口被拒绝

注意

早停触发后树列表截断到 bestIteration+1,lossHistory 同步截断

注意

write 只保存算法、目标、学习率、baseScore 与树;读回时其余超参数取 Builder 默认值

参见:basalt.ml.BoostingAlgorithm, basalt.ml.BoostingObjective, basalt.ml.DecisionTree

方法

builder() → Builderstatic

创建构造器,参数全部取默认值

返回

新的 Builder 实例

fit(Matrix features, double[] targets) → HistogramGradientBoosting

分箱、切分验证集并逐轮提升

先按 validationFraction 用 seed 打乱行号,前若干行作验证集,其余作训练集;baseScore 取训练集标签均值,LOGISTIC 下取该均值的对数几率。每轮计算梯度与 hessian、生长一棵树、以 learningRate 累加到原始得分,并记录训练与验证损失。

注意

验证集大小取 round(rows*validationFraction),下限 1,上限 rows-2

注意

featureFraction 小于 1 时,第 i 轮用 seed + i*7919 抽取 ceil(fraction*featureCount) 个特征

参数
  • features (Matrix) – 训练特征矩阵,行数为样本数

  • targets (double[]) – 目标数组,长度须等于行数;LOGISTIC 时取值须为 0 或 1

返回

this,已完成拟合

抛出
  • IllegalArgumentException – 目标数量与行数不一致、含非有限值,或 LOGISTIC 标签不是 0 或 1

predictRaw(Matrix features) → double[]

输出原始得分,未过 sigmoid

结果以 baseScore 为初值,逐棵树以 learningRate 加权累加叶值。行数乘树数不小于 2000 万时转交原生集成预测内核,否则在 Java 侧逐树累加。

参数
  • features (Matrix) – 特征矩阵,列数须等于拟合时的特征数

返回

长度为行数的原始得分数组

抛出
  • IllegalStateException – 尚未拟合(树列表为空)

  • IllegalArgumentException – 列数不匹配或含非有限值

predictProbability(Matrix features) → double[]

输出正类概率,等于 sigmoid(原始得分)

注意

sigmoid 按符号分支实现,负值不经过 exp 溢出

参数
  • features (Matrix) – 特征矩阵,列数须等于拟合时的特征数

返回

长度为行数的概率数组,取值 (0, 1)

抛出
  • IllegalStateException – 目标不是 LOGISTIC(该校验先于拟合状态校验)

predict(Matrix features) → double[]

输出预测值,LOGISTIC 下为 0/1 标签

回归直接返回原始得分;LOGISTIC 把 sigmoid(原始得分) 与 0.5 比较,大于等于 0.5 取 1.0,否则取 0.0。

参数
  • features (Matrix) – 特征矩阵,列数须等于拟合时的特征数

返回

长度为行数的预测数组

抛出
  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 列数不匹配或含非有限值

lossHistory() → double[]

每轮训练集平均损失

平方误差目标记录 0.5*残差^2 的均值;LOGISTIC 记录 softplus(raw) - target*raw 的均值,数值上等价于二元交叉熵。

注意

早停后长度等于保留下来的树数

返回

长度为实际训练轮数的副本;未拟合为空数组

validationHistory() → double[]

每轮验证集平均损失

返回

长度为实际训练轮数的副本;未设置 validationFraction 或未拟合时为空数组

featureImportances() → double[]

归一化的特征重要性,总和为 1

口径与 DecisionTree 一致:每次分裂的增益乘以该节点样本数,按特征累加后整体归一化到总和 1。分裂发生在特征子集上时,未参与该轮的特征不增加。

注意

读回的模型不携带重要性,返回全 0

返回

长度为特征数的副本;未拟合为空数组

treeCount() → int

已训练的树数

返回

树数;未拟合为 0,早停后小于 iterations

bestIteration() → int

验证损失最优的轮次下标

返回

最优轮次;无验证集时为最后一轮,未拟合为 iterations-1

kind() → ModelKind

持久化类型标识

返回

ModelKind.HISTOGRAM_BOOSTING

write(ModelWriter writer)

按 Persistable 契约写出提升模型

写入算法序号、目标序号、learningRate、baseScore、特征数、树数与各棵树的节点数组。maxDepth、maxLeaves、lambda 等超参数不参与序列化。

参数
  • writer (ModelWriter) – 目标二进制写入器

read(ModelReader reader) → HistogramGradientBoostingstatic

从二进制流重建提升模型

注意

读回后 lossHistory 与 validationHistory 为空数组,featureImportances 全为 0

注意

bestIteration 置为树数减 1,训练相关字段不恢复

参数
  • reader (ModelReader) – 已定位到本对象载荷起点的读取器

返回

新的 HistogramGradientBoosting 实例,可直接预测

抛出
  • ModelFormatException – 算法或目标序号越界,或特征数不大于 0、树数不在 [1, 100000]

enum ImpurityCriterion

决策树用于最大化信息增益的节点不纯度

GINI 计算 1 - Σp^2,ENTROPY 计算 -Σ p*log2(p),两者绑定 TreeTask.CLASSIFICATION。MSE 绑定 TreeTask.REGRESSION,其 impurity 方法直接抛出 IllegalStateException,因为回归分裂改用和与平方和的代数等价形式,不经过类别计数。

每个常量在构造时绑定任务,task() 暴露该绑定。DecisionTree.Builder 在 build() 时校验 criterion.task() 与 task 一致,准则与任务不会在运行期错配。

示例
ImpurityCriterion criterion = ImpurityCriterion.ENTROPY;

DecisionTree tree = DecisionTree.builder()
        .criterion(criterion)
        .task(criterion.task())
        .maxDepth(4)
        .build();

注意

骨架中的 ENTROPY 与 MSE 条目是枚举常量,签名里出现的参数即构造时传入的任务标记

注意

MSE 只作任务标识,逐节点计算不经过 impurity

参见:basalt.ml.DecisionTree, basalt.ml.TreeTask

方法

task() → TreeTask

该准则绑定的任务类型

注意

Builder 用它校验准则与任务是否匹配

返回

构造时传入的 TreeTask

final class IsolationForest implements Estimator, Persistable

随机轴对齐切分的无监督孤立森林异常检测器。

每棵树在 min(行数, maxSamples) 个无放回抽样的样本上递归切分:随机挑一个取值不全相同的特征,在该列最小值与最大值之间均匀取切点,小于等于切点的样本进左子树;样本数不超过 1、深度达到 max(1, ceil(log2(effectiveMaxSamples)))、或所选特征无区分度时成为叶节点,叶节点保存 depth + c(n)。

路径长度归一化 s(x, n) = 2^(-E(h(x))/c(n)),E(h) 为样本在各棵树上路径长度的平均值,c(n) 为二叉搜索树平均路径修正项:n <= 1 取 0,n == 2 取 1,否则取 2*(ln(n-1) + EulerGamma) - 2*(n-1)/n。分数落在 (0, 1],越接近 1 越异常,约 0.5 为平均路径长度。

contamination 只影响判决阈值:拟合末尾对训练集的 0.5 - s 升序排序,取下标 max(0, min(rows-1, floor(rows * contamination))) 处的值作为 threshold。decisionFunction 返回 0.5 - s - threshold,predict 对非负者给 +1.0、负者给 -1.0。

示例
Matrix features = Matrix.fromRows(new double[][] {
        {0.0, 0.1}, {0.2, 0.0}, {0.1, 0.2}, {0.15, 0.1},
        {9.0, 9.2}, {9.4, 8.8}, {10.0, 9.0}, {0.3, 0.25}
});

IsolationForest forest = IsolationForest.builder()
        .trees(100)
        .maxSamples(256)
        .contamination(0.25)
        .seed(42L)
        .build()
        .fit(features);

double[] score = forest.anomalyScore(features);
double[] decision = forest.decisionFunction(features);
double[] label = forest.predict(features);

注意

默认 trees=100、maxSamples=256、contamination=0.1、seed=42;trees 须为正,maxSamples 须 >= 2,contamination 须在 (0, 0.5) 开区间内

注意

随机性全部来自 seed:主随机源为每棵树派生一个子种子,同 seed 同数据得到相同的树与阈值

注意

write 保存全部超参数、featureCount、effectiveMaxSamples、threshold 与树结构,read 直接沿用读入的阈值,不重新打分

注意

样本数少于 maxSamples 时 effectiveMaxSamples 退化为行数,c(n) 与树高上限随之按行数计算

参见:basalt.ml.Estimator, basalt.core.Persistable, basalt.ml.Estimators

方法

builder() → Builderstatic

创建构造器,超参数取默认值。

返回

新的 Builder 实例,trees=100、maxSamples=256、contamination=0.1、seed=42

fit(Matrix features) → IsolationForest

仅凭特征拟合,等价于 fit(features, null)。

参数
  • features (Matrix) – 训练特征矩阵,行数为样本数,列数为特征数

返回

this,已完成拟合并可打分

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – 特征含非有限值

fit(Matrix features, double[] ignoredTargets) → IsolationForest

建树并对训练集打分确定阈值。

effectiveMaxSamples 取行数与 maxSamples 的较小值,树高上限为 max(1, ceil(log2(effectiveMaxSamples)))。每棵树用主随机源派生的子种子做无放回抽样,再随机选一个取值不全相同的特征、在列最小与最大之间均匀取切点递归下分。

全部树建成后对训练集计算 0.5 - s,升序排序并取 contamination 对应的分位值作为 threshold,供 decisionFunction 与 predict 使用。

注意

effectiveMaxSamples 极小时树高上限至少为 1

注意

每棵树的抽样与切点都由各自的子种子决定,treeCount 棵树互相独立

参数
  • features (Matrix) – 训练特征矩阵,行数为样本数

  • ignoredTargets (double[]) – 占位参数,内容被完全忽略,可为 null

返回

this,已完成拟合

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – 特征含非有限值

anomalyScore(Matrix features) → double[]

计算归一化异常分数 2^(-E(h)/c(n))。

注意

E(h) 为样本在各棵树上的平均路径长度,归一化分母 c(n) 用 effectiveMaxSamples 计算

注意

c(n) 下限截到 1e-12,避免退化数据导致除零

参数
  • features (Matrix) – 待打分特征矩阵,列数须等于拟合时的特征数

返回

长度等于行数的分数数组,取值 (0, 1],越接近 1 越异常

抛出
  • IllegalStateException – 尚未拟合(树列表为空)

  • IllegalArgumentException – 列数不符或特征含非有限值

decisionFunction(Matrix features) → double[]

返回以阈值为零点的偏移分数。

注意

阈值由拟合时训练集的 contamination 分位确定,未拟合时无法得到有意义的零点

参数
  • features (Matrix) – 待打分特征矩阵,列数须等于拟合时的特征数

返回

0.5 - s - threshold,正值表示正常点,负值表示异常点

抛出
  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 列数不符或特征含非有限值

predict(Matrix features) → double[]

输出 +1.0 正常、-1.0 异常。

注意

判定规则为 decisionFunction 结果不小于 0 时取 +1.0,否则取 -1.0

参数
  • features (Matrix) – 待预测特征矩阵,列数须等于拟合时的特征数

返回

长度等于行数的标签数组,正常为 +1.0,异常为 -1.0

抛出
  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 列数不符或特征含非有限值

kind() → ModelKind

返回模型类型标识。

返回

ModelKind.ISOLATION_FOREST

write(ModelWriter writer)

写入超参数、阈值与全部树结构。

注意

依次写入 trees、maxSamples、contamination、seed、featureCount、effectiveMaxSamples、threshold 与树数

注意

阈值随模型一并保存,读回后不再重新计算

参数
  • writer (ModelWriter) – 目标写入器,由调用方负责容器头与提交

抛出
  • IllegalStateException – 尚未拟合(树列表为空)

read(ModelReader reader) → IsolationForeststatic

重建孤立森林模型。

参数
  • reader (ModelReader) – 已完成容器头解析的读取器

返回

含已训练树与阈值的模型实例,可直接用于 predict

抛出
  • ModelFormatException – 树数、特征数或实际读到的树数不为正

final class KBinsDiscretizer implements Transformer, Estimator

按分位数、等宽或一维 K-Means 把连续特征离散为箱。

拟合逐列计算 nBins+1 个边界:edges[0] 取该列最小值、edges[nBins] 取最大值,中间边界按策略生成。UNIFORM 取 min + b*(max-min)/nBins;QUANTILE 先排序该列,再在位置 (rows-1)*b/nBins 处对相邻样本做线性插值;KMEANS 在该列上运行一维 KMeans(clusters=nBins、maxIterations=50、seed=42),取排序后相邻质心的中点作为边界。列内取值全相同时,中间边界全部等于该常量。

变换用边界比较定位:从 b=1 起找第一个满足 value < edges[b] 的 b,返回 b-1;没有任何边界满足时落入最后一箱,因此区间是左闭右开,恰好等于边界值的样本归入右侧箱。ORDINAL 输出与输入同宽、元素为箱序号 0..nBins-1;ONEHOT_DENSE 输出宽度为 特征数 * nBins,每个原始特征占一段连续列,命中位置置 1。

逆变换用箱中点 0.5*(edges[b] + edges[b+1]) 还原:ORDINAL 先把箱序号四舍五入并夹到 [0, nBins-1];ONEHOT_DENSE 对每段取最大值所在的列,并列时取靠前的箱。

示例
Matrix x = Matrix.fromRows(new double[][] {
        {0.0, 10.0}, {0.5, 12.0}, {1.0, 14.0},
        {2.0, 16.0}, {4.0, 18.0}, {8.0, 20.0}
});

KBinsDiscretizer discretizer = KBinsDiscretizer.builder()
        .nBins(3)
        .strategy(KBinsDiscretizer.Strategy.QUANTILE)
        .encode(KBinsDiscretizer.Encode.ORDINAL)
        .build()
        .fit(x);

Matrix binned = discretizer.transform(x);
Matrix restored = discretizer.inverseTransform(binned);
double[][] edges = discretizer.binEdges();

注意

默认 nBins=5、strategy=QUANTILE、encode=ORDINAL;nBins 须 >= 2

注意

变换前必须 fit,否则抛 IllegalStateException;输入列数须等于拟合时的特征数

注意

列内取值全相同的特征恒落在最后一箱,因为没有任何边界能严格大于该值

注意

KMEANS 策略的随机性固定为 seed=42,同一列多次拟合得到相同边界

注意

write 保存 nBins、策略、编码与逐列边界,read 后无需重新拟合即可 transform

参见:basalt.ml.Transformer, basalt.ml.KMeans, basalt.ml.OneHotEncoder

方法

builder() → Builderstatic

创建构造器,nBins=5、QUANTILE、ORDINAL。

返回

新的 Builder 实例

fit(Matrix features) → KBinsDiscretizer

仅凭特征拟合,等价于 fit(features, null)。

参数
  • features (Matrix) – 训练特征矩阵,列数决定边界组数

返回

this,已算出逐列边界

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – 特征含非有限值

fit(Matrix features, double[] ignoredTargets) → KBinsDiscretizer

逐列计算 nBins+1 个箱边界。

每列取最小与最大值作为首尾边界,中间边界按策略生成;列内取值全相同时中间边界退化为该常量。

注意

QUANTILE 的插值位置为 (rows-1)*b/nBins,等价于 numpy 默认的 linear 分位

注意

KMEANS 每列单独跑一次一维 KMeans,迭代上限 50、种子 42

参数
  • features (Matrix) – 训练特征矩阵,列数决定边界组数

  • ignoredTargets (double[]) – 占位参数,内容被完全忽略,可为 null

返回

this,已完成拟合

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – 特征含非有限值

transform(Matrix features) → Matrix

把特征映射为箱序号或 One-Hot。

注意

判定为 value < edges[b],等于边界值的样本进入右侧箱

注意

ONEHOT_DENSE 的列顺序为特征优先,每个特征的 nBins 列连续排列

参数
  • features (Matrix) – 待转换矩阵,列数须等于拟合时的特征数

返回

ORDINAL 为 行数 × 特征数 的箱序号矩阵;ONEHOT_DENSE 为 行数 × (特征数 * nBins) 的 0/1 矩阵

抛出
  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 列数不符或特征含非有限值

inverseTransform(Matrix transformed) → Matrix

用箱中点还原近似原特征。

注意

ORDINAL 先把箱序号四舍五入再夹到 [0, nBins-1],越界值被截断

注意

ONEHOT_DENSE 取每段最大值位置,并列时取靠前的箱;全零段落到第 0 箱

注意

还原值只保证落在对应箱内,不等于原始输入

参数
  • transformed (Matrix) – 形状与 transform 输出一致的矩阵

返回

行数 × 特征数 的近似原特征矩阵,元素为对应箱的中点

抛出
  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 列数不符(ORDINAL 需特征数列,ONEHOT_DENSE 需特征数 * nBins 列)或含非有限值

predict(Matrix features) → double[]

返回展平后的离散结果。

注意

元素仍是箱序号或 0/1,便于把转换结果当作估计器输出消费

参数
  • features (Matrix) – 待转换矩阵,列数须等于拟合时的特征数

返回

transform 结果按行优先展平的一维数组,长度为 行数 × 输出列数

抛出
  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 列数不符或特征含非有限值

binEdges() → double[][]

返回逐列的箱边界副本。

注意

返回深拷贝,修改不影响模型内部边界

返回

二维数组 [特征数][nBins+1],首尾为列最小值与最大值

抛出
  • IllegalStateException – 尚未拟合

kind() → ModelKind

返回模型类型标识。

返回

ModelKind.KBINS_DISCRETIZER

write(ModelWriter writer)

写入箱数、策略、编码与逐列边界。

注意

策略与编码以枚举 ordinal 落盘

注意

按特征顺序写入每组 nBins+1 个边界

参数
  • writer (ModelWriter) – 目标写入器,由调用方负责容器头与提交

抛出
  • IllegalStateException – 尚未拟合

read(ModelReader reader) → KBinsDiscretizerstatic

读回箱数、策略、编码与逐列边界。

参数
  • reader (ModelReader) – 已完成容器头解析的读取器

返回

已可直接 transform 的实例

抛出
  • ModelFormatException – 箱数小于 2、特征数不为正,或策略、编码序号越界

final class KFold

K 折交叉验证划分器,默认打乱且种子为 42。

划分是位置切分:先按 shuffle 与 seed 得到行序(不打乱时即 0..rows-1),第 f 折的测试区间为 [f*rows/folds, (f+1)*rows/folds),其余行按行序首尾拼接成训练集。行数不能被折数整除时,多出的样本落在靠后的折上。

是否打乱由 shuffle 决定,构造器默认 true,与 sklearn 的默认 false 不同;seed 只在 shuffle 为 true 时起作用,相同 seed 与相同数据得到完全一致的划分。

每折以 DataSplit.Fold 返回四个字段:trainFeatures、trainTargets、testFeatures、testTargets,均为按索引复制出的新数组,可安全修改。

示例
Matrix x = Matrix.fromRows(new double[][] {
        {0.0, 1.0}, {1.0, 0.0}, {1.0, 1.0}, {2.0, 2.0},
        {2.0, 3.0}, {3.0, 2.0}, {3.0, 3.0}, {4.0, 4.0}
});
double[] y = {0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0};

KFold kfold = new KFold(4);
List<DataSplit.Fold> folds = kfold.split(x, y);

DataSplit.Fold first = folds.get(0);
Matrix trainX = first.trainFeatures();
Matrix testX = first.testFeatures();
int count = kfold.folds();
boolean shuffled = kfold.shuffle();

注意

构造器只校验 folds >= 2,folds 超过样本数的检查延到 split 阶段

注意

类本身不持有数据,同一实例可对不同矩阵反复 split

注意

目标数组只随行搬运,划分过程不看标签取值,不做分层

参见:basalt.ml.DataSplit, basalt.ml.GridSearchCV, basalt.ml.StratifiedKFold

构造器

KFold(int folds)

按折数构造,默认打乱且种子为 42。

注意

等价于 KFold(folds, true, 42L)

参数
  • folds (int) – 折数,须 >= 2

抛出
  • IllegalArgumentException – folds 小于 2

KFold(int folds, boolean shuffle, long seed)

指定折数、是否打乱与随机种子。

参数
  • folds (int) – 折数,须 >= 2

  • shuffle (boolean) – 是否在划分前打乱行序;false 时按原始行号顺序切分

  • seed (long) – 打乱所用随机源种子,shuffle 为 false 时无效

抛出
  • IllegalArgumentException – folds 小于 2

方法

folds() → int

返回折数。

返回

构造时给定的折数

shuffle() → boolean

返回是否打乱。

返回

true 表示划分前按 seed 打乱行序

split(Matrix features, double[] targets) → List<DataSplit.Fold>

生成各折的训练与测试划分。

第 f 折测试区间取 [f*rows/folds, (f+1)*rows/folds),训练集为其余区间的拼接,因此每折训练集大小等于 rows 减去该折测试集大小。

注意

返回的矩阵与数组都是新分配的副本,与原数据不共享存储

参数
  • features (Matrix) – 特征矩阵,行数为样本数

  • targets (double[]) – 目标数组,长度须等于行数,仅随行搬运

返回

长度为 folds 的列表,每项为 DataSplit.Fold,含 trainFeatures、trainTargets、testFeatures、testTargets

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – 折数大于样本数、目标数量与行数不一致,或数据含非有限值

final class KMeans implements Estimator, Persistable

K-Means++ 播种的 Lloyd 迭代聚类,支持多次重启。

分配步逐样本计算到 k 个质心的平方欧氏距离,按行区间并行执行;质心累加与求均值为串行循环,且复用预分配缓冲区。多次重启各自独立初始化,保留惯性最小的一次结果。

第 r 次重启使用 seed + 7919r 作为随机源种子。空簇修复从当前分配中挑选距离所属质心最远、且所属簇样本数大于 1 的样本,把它捐给空簇并以该样本位置作为新质心;找不到合格捐赠者时退化为全局最远样本。

示例
Matrix features = Matrix.fromRows(new double[][] {
    {0.0, 0.0}, {0.4, 0.2}, {0.1, 0.5},
    {9.6, 9.8}, {10.0, 10.2}, {9.4, 9.9}
});
KMeans kmeans = KMeans.builder()
        .clusters(2)
        .restarts(4)
        .maxIterations(200)
        .seed(7L)
        .build()
        .fit(features);
double[] assignment = kmeans.predict(features);
double[] distance = kmeans.transform(features);
Matrix centers = kmeans.centroids();
double inertia = kmeans.inertia();

注意

tolerance 作用于质心位移:全部质心各分量位移的平方和不超过 tolerance² 时停止迭代

注意

inertia 在迭代结束后按最终质心重新计算,等于各样本到最近质心平方距离之和,可能与最后一轮分配时的值略有差异

注意

样本数不少于 1024、特征数不少于 8 且原生内核可用时,整个拟合交给原生实现

注意

特征数不少于 128 时,单轮分配步也可能切换到原生内核

参见:basalt.ml.Estimator, basalt.core.Persistable

方法

builder() → Builderstatic

创建 KMeans 构建器。

返回

参数取默认值的新 Builder 实例

fit(Matrix features) → KMeans

只用特征拟合,目标数组缺省为 null。

参数
  • features (Matrix) – 训练样本矩阵,行是样本、列是特征

返回

this,便于链式调用

fit(Matrix features, double[] ignoredTargets) → KMeans

执行 K-Means++ 初始化与 Lloyd 迭代。

首个质心从样本中均匀随机抽取,后续质心按到最近已有质心的平方距离加权抽取;若全部距离之和为 0,则改用簇序号对样本数取模。每次重启跑满收敛条件或 maxIterations,取惯性最小者。

注意

每次重启都新建 Random,因此同一 seed 与 restarts 组合可复现结果

参数
  • features (Matrix) – 训练样本矩阵,行是样本、列是特征;元素必须有限

  • ignoredTargets (double[]) – 占位参数;聚类忽略监督目标,可为 null

返回

this,便于链式调用

抛出
  • IllegalArgumentException – features 为 null 或含非有限值,或簇数大于样本数

predict(Matrix features) → double[]

把每个样本分配给最近的质心。

参数
  • features (Matrix) – 样本矩阵,列数须与拟合时一致

返回

长度为样本数的簇索引,以 double 表示

抛出
  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 特征列数与拟合时不一致

transform(Matrix features) → double[]

返回各样本到其所属质心的平方距离。

先按最近质心确定归属,再取该质心与样本的平方欧氏距离。返回一维数组,每个样本一个标量,而不是距离矩阵;需要欧氏距离时自行开方。

参数
  • features (Matrix) – 样本矩阵,列数须与拟合时一致

返回

长度为样本数的平方距离数组

抛出
  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 特征列数与拟合时不一致

centroids() → Matrix

返回最终质心矩阵。

返回

簇数 × 特征数 的矩阵,每行一个质心

抛出
  • IllegalStateException – 尚未拟合

inertia() → double

返回最优重启的惯性值。

返回

样本到最近质心平方距离之和;未拟合时为 0

iterations() → int

返回最优重启实际执行的迭代轮数。

返回

1 到 maxIterations 之间的轮数;未拟合时为 0

restarts() → int

返回已完成的随机重启次数。

返回

拟合后等于配置的 restarts;未拟合或由 read 重建的模型为 0

kind() → ModelKind

返回模型类型标识。

返回

ModelKind.KMEANS

write(ModelWriter writer)

写入簇数、特征数、惯性、迭代轮数与质心。

注意

tolerance、seed、restarts 与 threads 不写入流,read 后回到 Builder 默认值

参数
  • writer (ModelWriter) – 目标写入器,由调用方负责容器头与关闭

抛出
  • IllegalStateException – 尚未拟合

read(ModelReader reader) → KMeansstatic

从序列化流重建 KMeans 模型。

参数
  • reader (ModelReader) – 已完成容器头解析的读取器

返回

只恢复质心与统计量的模型实例,可直接用于 predict

抛出
  • ModelFormatException – 簇数或特征数不为正

final class KNearestNeighbors implements Estimator

统一权重的 KNN 分类器。

fit 只保存训练集的副本(特征 copy、标签 clone),不做归一化或索引结构;predict 对每个查询样本线性扫描全部训练行,用距离度量维护容量为 k 的最大堆,堆中即 k 个最近邻,再按标签多数投票。

投票是统一权重,距离不参与加权;票数相同时选择数值更小的标签,因此结果与 HashMap 迭代顺序无关,完全可复现。单次查询的时间为 O(n·d),额外内存为 O(k) 加上训练集副本。

示例
Matrix x = Matrix.fromRows(new double[][]{{0, 0}, {0, 1}, {1, 0}, {1, 1}});
double[] y = {0, 1, 1, 0};
KNearestNeighbors knn = KNearestNeighbors.builder()
        .k(3)
        .metric(DistanceMetric.MANHATTAN)
        .build()
        .fit(x, y);
double[] labels = knn.predict(x);

注意

k 在 build() 时校验为正,fit 时再校验不超过训练样本数

注意

特征未标准化,量纲差异会主导欧氏距离

注意

训练集在 fit 时复制,之后修改原 Matrix 不影响模型

参见:basalt.ml.KNeighborsRegressor, basalt.ml.DistanceMetric, basalt.ml.KNearestNeighbors.Builder

方法

builder() → Builderstatic

创建构建器,默认 k=5、欧氏距离。

注意

每次调用都返回独立实例,可安全地分别配置

返回

新的 Builder,字段取默认值

fit(Matrix features, double[] targets) → KNearestNeighbors

保存训练集副本,不做任何预计算。

注意

重复 fit 会用新数据覆盖旧训练集

参数
  • features (Matrix) – 训练特征矩阵,列数即特征维数

  • targets (double[]) – 训练标签数组,取值可以是任意 double

返回

this

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – k 大于训练样本数,或行数与标签长度不符、数据含非有限值

predict(Matrix features) → double[]

对每个样本取 k 近邻多数投票。

注意

平票时返回数值更小的标签,保证确定性

参数
  • features (Matrix) – 待预测特征矩阵,列数须等于训练特征数

返回

每行一个训练集中出现过的标签值

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

final class KNeighborsRegressor implements Estimator

统一权重的 KNN 回归器。

与分类版共享同一套流程:fit 只复制训练集,predict 逐样本线性扫描并用容量为 k 的最大堆保留最近邻。区别在聚合方式——对 k 个邻居的目标值取算术平均,不做距离加权。

单次查询的时间为 O(n·d),额外内存为 O(k) 加上训练集副本。目标值未做任何变换,因此预测结果始终落在训练目标的最小值与最大值之间,不会外推。

示例
Matrix x = Matrix.fromRows(new double[][]{{0, 0}, {0, 1}, {1, 0}, {1, 1}});
double[] y = {0.0, 1.0, 1.0, 2.0};
KNeighborsRegressor regressor = KNeighborsRegressor.builder().k(2).build().fit(x, y);
double[] predictions = regressor.predict(x);

注意

k 在 fit 时校验不超过训练样本数

注意

距离加权、叶节点裁剪等加速结构均未实现

参见:basalt.ml.KNearestNeighbors, basalt.ml.DistanceMetric

方法

builder() → Builderstatic

创建构建器,默认 k=5、欧氏距离。

返回

新的 Builder,字段取默认值

fit(Matrix features, double[] targets) → KNeighborsRegressor

保存训练集副本,不做预计算。

参数
  • features (Matrix) – 训练特征矩阵

  • targets (double[]) – 训练目标数组,长度等于行数

返回

this

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – k 大于训练样本数,或形状不符、数据含非有限值

predict(Matrix features) → double[]

对 k 个最近邻的目标值取平均。

参数
  • features (Matrix) – 待预测特征矩阵,列数须等于训练特征数

返回

每行一个连续预测值,为 k 个邻居目标的算术平均

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

final class Kernel

四种半正定核函数:LINEAR、RBF、POLY 与 SIGMOID。

四种核的定义为 LINEAR K(x, y) = x · y;RBF K(x, y) = exp(-gamma * ||x - y||^2);POLY K(x, y) = (gamma * (x · y) + coef0)^degree;SIGMOID K(x, y) = tanh(gamma * (x · y) + coef0)。SIGMOID 不保证半正定,仅在参数合适时可用作核。

gamma 控制内积或距离的缩放:RBF 中越大核越窄、单个样本影响半径越小;POLY 与 SIGMOID 中缩放内积后再叠加 coef0。degree 只对 POLY 生效,coef0 对 POLY 与 SIGMOID 生效,LINEAR 不使用这三个参数。

评估有两条路径:evaluate 直接在原数组上按偏移与长度计算单点核值,避免为每个样本对分配临时向量;gram 逐行逐列调用 evaluate 组装批量的 Gram 矩阵。

示例
Matrix a = Matrix.fromRows(new double[][] {{1.0, 2.0}, {2.0, 1.0}});
Matrix b = Matrix.fromRows(new double[][] {{0.0, 1.0}, {3.0, 3.0}});

Kernel kernel = Kernel.rbf(0.5);
double value = kernel.evaluate(a.data(), 0, b.data(), 0, 2);
Matrix gram = kernel.gram(a, b);

Kernel poly = Kernel.poly(3, 0.25, 1.0);
double degree = poly.degree();
double coef0 = poly.coef0();

注意

构造器允许 gamma 取 0,此时 evaluate 内部改用 1/max(1, length) 作为缩放,等价于按维数缩放;rbf/poly/sigmoid 工厂则要求 gamma 严格为正

注意

linear() 固定 gamma=1.0、degree=3、coef0=0.0;sigmoid 工厂固定 degree=3,只有 poly 工厂会改写 degree

注意

gram 不做分块与原生加速,时间复杂度为 rows(a) * rows(b) * 特征数

注意

write 按类型序号、gamma、degree、coef0 的顺序落盘,read 依赖 Type 枚举的声明顺序

参见:basalt.ml.SVC, basalt.ml.KernelRidge, basalt.ml.KernelPCA

构造器

Kernel(Type type, double gamma, int degree, double coef0)

按显式类型与参数构造核函数。

注意

构造器不按类型裁剪参数,未参与计算的字段照原样保存

参数
  • type (Type) – 核类型,取 Type 枚举值,不接受 null

  • gamma (double) – 缩放系数,须有限且非负;取 0 时评估按 1/max(1, length) 替代

  • degree (int) – POLY 的多项式次数,须 >= 1

  • coef0 (double) – POLY 与 SIGMOID 的常数项,须有限

返回

持有给定参数的核函数实例

抛出
  • NullPointerException – type 为 null

  • IllegalArgumentException – gamma 非有限或为负、degree 小于 1、coef0 非有限

方法

linear() → Kernelstatic

构造线性核 K(x, y) = x · y。

注意

三个参数都不参与 LINEAR 的计算,仅随实例保存并参与序列化

返回

gamma=1.0、degree=3、coef0=0.0 的 LINEAR 核

rbf(double gamma) → Kernelstatic

构造高斯核 exp(-gamma * ||x - y||²)。

参数
  • gamma (double) – 尺度系数,须为正且有限;越大核越窄、影响半径越小

返回

degree=3、coef0=0.0 的 RBF 核

抛出
  • IllegalArgumentException – gamma 小于等于 0 或非有限

poly(int degree, double gamma, double coef0) → Kernelstatic

构造多项式核 (gamma * x·y + coef0)^degree。

参数
  • degree (int) – 多项式次数,须 >= 1

  • gamma (double) – 内积缩放系数,须为正且有限

  • coef0 (double) – 加在内积上的常数项,须有限

返回

POLY 核实例

抛出
  • IllegalArgumentException – gamma 非正或非有限,或 degree 小于 1、coef0 非有限

sigmoid(double gamma, double coef0) → Kernelstatic

构造 sigmoid 核 tanh(gamma * x·y + coef0)。

参数
  • gamma (double) – 内积缩放系数,须为正且有限

  • coef0 (double) – 双曲正切内的偏移量,须有限

返回

degree=3 的 SIGMOID 核实例

抛出
  • IllegalArgumentException – gamma 非正或非有限,或 coef0 非有限

type() → Type

返回核类型。

返回

Type 枚举值 LINEAR、RBF、POLY 或 SIGMOID

gamma() → double

返回 gamma 系数。

返回

RBF、POLY、SIGMOID 的尺度系数;LINEAR 固定为 1.0

degree() → int

返回多项式次数。

返回

POLY 的次数;其余类型固定为 3

coef0() → double

返回常数项 coef0。

返回

POLY 与 SIGMOID 的常数项;LINEAR 与 RBF 为 0.0

evaluate(double[] x, int xOffset, double[] y, int yOffset, int length) → double

按偏移与长度计算两点核值。

注意

gamma 为 0 时内部改用 1/max(1, length),即按维数缩放

注意

不检查偏移与长度的越界,由调用方保证区间合法

参数
  • x (double[]) – 左向量所在的数组

  • xOffset (int) – 左向量在 x 中的起始下标

  • y (double[]) – 右向量所在的数组

  • yOffset (int) – 右向量在 y 中的起始下标

  • length (int) – 参与计算的维数

返回

核函数值:LINEAR 为内积,RBF 落在 (0, 1],POLY 与 SIGMOID 可为任意实数

gram(Matrix a, Matrix b) → Matrix

计算两批样本之间的 Gram 矩阵。

注意

逐元素调用 evaluate,串行双重循环,无分块或原生加速

参数
  • a (Matrix) – 左样本矩阵,行数为样本数,列数为特征数

  • b (Matrix) – 右样本矩阵,列数须与 a 相同

返回

rows(a) × rows(b) 的矩阵,第 i 行第 j 列为 K(a 的第 i 行, b 的第 j 行)

抛出
  • IllegalArgumentException – 两个矩阵的列数不同

write(ModelWriter writer)

写入类型序号、gamma、degree 与 coef0。

注意

依次写入一个 int 序号、一个 double、一个 int 与一个 double,共四个字段

注意

类型以 Type.ordinal() 落盘,read 依赖同一枚举顺序

参数
  • writer (ModelWriter) – 目标写入器,由调用方负责容器头与提交

read(ModelReader reader) → Kernelstatic

从序列化流重建核函数。

参数
  • reader (ModelReader) – 已完成容器头解析的读取器

返回

参数与写入时一致的 Kernel 实例

抛出
  • ModelFormatException – 类型序号不在 Type 枚举范围内

final class KernelDensity implements Estimator, Persistable

高斯与 TOPHAT 核的核密度估计,输出对数密度。

拟合不做任何参数估计,只把训练样本复制一份作为核中心集合,因此打分代价为查询点数、训练样本数与特征数三者之积。

GAUSSIAN 核下 log p(x) = -log(n) - d*log(bandwidth) - 0.5*d*log(2π) + log Σ exp(-||x - x_i||² / (2 * bandwidth²)),求和用减去最大项的方式做 log-sum-exp 以避免下溢;TOPHAT 核下以带宽为半径的球内命中数 hits 决定密度,log p(x) = log(hits / n) - [0.5*d*log(π) - logΓ(d/2 + 1) + d*log(bandwidth)],无命中时返回负无穷。

bandwidth 是唯一平滑参数:越大分布越平滑、峰值越低,方差约等于 bandwidth² 加上训练样本自身方差。sample 从训练行中均匀抽取一个中心再叠加噪声,GAUSSIAN 加各向同性正态噪声,TOPHAT 加逐维均匀噪声。

示例
Matrix train = Matrix.fromRows(new double[][] {
        {0.0}, {0.4}, {1.0}, {1.2}, {2.0}, {3.5}
});
Matrix query = Matrix.fromRows(new double[][] {{0.5}, {1.5}, {3.0}});

KernelDensity kde = KernelDensity.builder()
        .bandwidth(0.5)
        .kernel(KernelDensity.KernelType.GAUSSIAN)
        .build()
        .fit(train);

double[] logDensity = kde.scoreSamples(query);
Matrix drawn = kde.sample(100, 7L);
double bandwidth = kde.bandwidth();

注意

默认 bandwidth=1.0、kernel=GAUSSIAN;bandwidth 须为正且有限

注意

scoreSamples 与 predict 返回对数密度而非概率密度,需要密度时自行取 exp

注意

write 只保存 bandwidth、核类型、特征数与训练样本,模型无其他可训练状态

注意

TOPHAT 在稀疏数据上常出现查询点邻域内无训练样本的情况,此时整行为负无穷

参见:basalt.ml.Estimator, basalt.core.Persistable, basalt.ml.Kernel

方法

builder() → Builderstatic

创建构造器,bandwidth=1.0、核为 GAUSSIAN。

返回

新的 Builder 实例

fit(Matrix features) → KernelDensity

仅凭样本拟合,等价于 fit(features, null)。

参数
  • features (Matrix) – 训练样本矩阵,行数为样本数,列数为特征数

返回

this,已保存训练样本

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – 特征含非有限值

fit(Matrix features, double[] ignoredTargets) → KernelDensity

保存训练样本副本与特征数。

KDE 无需估计参数,拟合只把特征矩阵复制一份作为核中心集合,所有距离在打分时按需计算。

注意

保存的是副本,拟合后再修改原矩阵不影响模型

参数
  • features (Matrix) – 训练样本矩阵,行数为样本数

  • ignoredTargets (double[]) – 占位参数,内容被完全忽略,可为 null

返回

this,已完成拟合

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – 特征含非有限值

scoreSamples(Matrix features) → double[]

输出每个查询点的对数密度 log p(x)。

GAUSSIAN 下对每个查询点累加 -||x - x_i||²/(2*bandwidth²),再以 log-sum-exp 汇总并加上归一化常数;TOPHAT 下统计平方距离不超过 bandwidth² 的训练样本数,按球体积归一化。

注意

复杂度为查询行数 × 训练行数 × 特征数,无树结构或原生加速

注意

GAUSSIAN 的归一化常数包含 -log(n) 与 -d*log(bandwidth)

参数
  • features (Matrix) – 查询点矩阵,列数须等于拟合时的特征数

返回

长度等于行数的对数密度数组;TOPHAT 下无命中时为负无穷

抛出
  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 列数不符或特征含非有限值

sample(int nSamples, long seed) → Matrix

从拟合的密度中抽取随机样本。

注意

每个样本先均匀抽取一个训练行作为中心,再叠加噪声

注意

GAUSSIAN 的噪声为标准差等于 bandwidth 的各向同性正态噪声;TOPHAT 为每维 [-bandwidth, bandwidth] 上的均匀噪声

参数
  • nSamples (int) – 抽样个数,须为正

  • seed (long) – 随机源种子,仅影响本次抽样的结果

返回

nSamples × 特征数 的矩阵

抛出
  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – nSamples 小于等于 0

predict(Matrix features) → double[]

与 scoreSamples 等价,返回对数密度。

注意

沿用 scoreSamples 的实现,输出是打分而非分类标签

参数
  • features (Matrix) – 查询点矩阵,列数须等于拟合时的特征数

返回

长度等于行数的对数密度数组

抛出
  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 列数不符或特征含非有限值

bandwidth() → double

返回带宽。

返回

构造时给定的 bandwidth,正有限值

kind() → ModelKind

返回模型类型标识。

返回

ModelKind.KERNEL_DENSITY

write(ModelWriter writer)

写入带宽、核类型与训练样本。

注意

核类型以 KernelType.ordinal() 落盘

注意

训练样本按行优先展平后整体写入,读回时按特征数还原形状

参数
  • writer (ModelWriter) – 目标写入器,由调用方负责容器头与提交

抛出
  • IllegalStateException – 尚未拟合

read(ModelReader reader) → KernelDensitystatic

读回带宽、核类型与训练样本。

参数
  • reader (ModelReader) – 已完成容器头解析的读取器

返回

已可打分的模型实例

抛出
  • ModelFormatException – 核类型序号越界、特征数或样本数不为正

final class KernelPCA implements Estimator, Transformer, Persistable

核主成分分析:在核空间中心化后做特征分解的降维估计器。

fit 先用核函数在训练集上求 n × n Gram 矩阵,按行均值、列均值与全均值做双重中心化 K - 1K/n - K1/n + 1K1/n²,再用循环 Jacobi 对称特征分解求特征值与特征向量;特征值截断为非负、按降序取前 components 个,特征向量按 1/sqrt(λ) 缩放后存为 alphas,λ 不超过 1e-12 的分量缩放因子取 0。

transform 对新样本计算它与全部训练样本的核值,用拟合阶段缓存的 kFitRows 与 kFitAll 做同样的中心化,再与 alphas 逐分量做内积得到投影坐标。predict 只是把投影矩阵按行优先展开成扁平数组。

示例
Matrix features = Matrix.fromRows(new double[][] {
    {1.0, 2.0}, {2.0, 1.0}, {3.0, 4.0}, {4.0, 3.0}, {5.0, 6.0}
});
KernelPCA kpca = KernelPCA.builder()
        .components(2)
        .rbf(0.5)
        .build()
        .fit(features);
Matrix projected = kpca.transform(features);
double[] eigenvalues = kpca.eigenvalues();

注意

核函数默认 rbf(gamma=1.0),可用 kernel(Kernel)、rbf(gamma) 或 poly(degree, gamma, coef0) 替换

注意

components 不能超过样本数,否则 fit 抛 IllegalArgumentException

注意

Jacobi 迭代上限 60 轮、收敛阈值 1e-12,Builder 未暴露这两个参数的设值方法

注意

主方向符号按特征向量绝对值最大的分量为正固定,同一输入重复拟合可复现

注意

训练集与核行均值随模型一起序列化,预测时的内存占用与训练集规模成正比

参见:basalt.ml.Kernel, basalt.ml.PCA, basalt.ml.KernelPCA.Builder

方法

builder() → Builderstatic

创建构建器,默认 2 个分量、rbf(1.0) 核。

返回

新的 Builder,字段取默认值

fit(Matrix features) → KernelPCA

只用特征拟合,目标数组缺省为 null。

注意

等价于 fit(features, null),目标参数被忽略

参数
  • features (Matrix) – 训练样本矩阵,行是样本、列是特征;元素必须有限

返回

this,便于链式调用

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – features 含非有限值,或 components 大于样本数

fit(Matrix features, double[] ignoredTargets) → KernelPCA

计算中心化核矩阵并提取前若干核主成分。

核矩阵在训练集自身上求值后做双重中心化;Jacobi 分解得到的特征值截断为非负、降序排序,前 components 个特征向量按 1/sqrt(λ) 缩放为 alphas。

注意

时间与内存都是 O(n²),n 为训练样本数

注意

特征值不大于 1e-12 的分量缩放因子取 0,该分量投影恒为 0

参数
  • features (Matrix) – 训练样本矩阵,行是样本、列是特征;元素必须有限

  • ignoredTargets (double[]) – 占位参数;核 PCA 忽略监督目标,可为 null

返回

this,便于链式调用

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – features 含非有限值,或 components 大于样本数

transform(Matrix features) → Matrix

把样本投影到核主成分坐标。

注意

每个样本都要与全部训练样本求核值,代价为 O(m·n) 次核求值

参数
  • features (Matrix) – 样本矩阵,列数须等于训练特征数

返回

样本数 × components 的投影矩阵

抛出
  • NullPointerException – features 为 null

  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

predict(Matrix features) → double[]

返回投影结果的扁平数组。

等价于 transform(features).toArray(),按行优先展开,便于接入只需要 double[] 的下游流程。

参数
  • features (Matrix) – 样本矩阵,列数须等于训练特征数

返回

长度为 样本数 × components 的数组

抛出
  • NullPointerException – features 为 null

  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

eigenvalues() → double[]

返回各核主成分的特征值。

注意

数值是中心化核矩阵的特征值,量纲与原始特征方差不同

返回

长度等于 components 的数组副本,非负且按降序排列

抛出
  • IllegalStateException – 尚未 fit

kind() → ModelKind

返回模型类型标识。

返回

ModelKind.KERNEL_PCA

write(ModelWriter writer)

写入核函数、分量数、训练集与中心化统计量。

注意

写入顺序为核函数、分量数、特征数、训练样本数、全均值、训练数据、核行均值、特征值、alphas

注意

maxIterations 与 tolerance 不写入流,read 后回到 Builder 默认值

参数
  • writer (ModelWriter) – 目标写入器,由调用方负责容器头与关闭

抛出
  • IllegalStateException – 尚未 fit

read(ModelReader reader) → KernelPCAstatic

从序列化流重建 KernelPCA 模型。

注意

核函数按流中记录的类型与参数还原,不会退回默认的 rbf(1.0)

参数
  • reader (ModelReader) – 已完成容器头解析的读取器

返回

可直接用于 transform 与 predict 的模型实例

抛出
  • ModelFormatException – 分量数、特征数或训练样本数不为正

final class KernelRidge implements Estimator, Persistable

核岭回归:在核空间解 (K + alpha·I)α = y 的回归估计器。

fit 用核函数在训练集上求 n × n Gram 矩阵,对角线加 alpha 后用 Cholesky 分解解线性方程组,得到对偶系数 α;预测值是目标样本与全部训练样本核值的加权和,模型没有独立截距项。

Cholesky 分解对对角元取 max(sum, 1e-12) 作为抖动,半正定退化时不产生 NaN。alpha 越大解越平滑,对偶系数的绝对值整体变小。

示例
Matrix x = Matrix.fromRows(new double[][]{{0, 0}, {1, 0}, {0, 1}, {1, 1}});
double[] y = {0.0, 1.0, 1.0, 2.0};
KernelRidge model = KernelRidge.builder()
        .rbf(1.0)
        .alpha(0.1)
        .build()
        .fit(x, y);
double[] predictions = model.predict(x);
double[] dual = model.dualCoef();

注意

核函数默认 rbf(gamma=1.0),可用 kernel(Kernel)、rbf(gamma) 或 poly(degree, gamma, coef0) 替换

注意

alpha 必须严格为正且有限,在 build() 时校验

注意

训练集与对偶系数一起序列化,预测代价与训练样本数成正比

注意

没有截距项:目标未中心化时预测会带系统性偏移

参见:basalt.ml.Kernel, basalt.ml.Ridge, basalt.ml.KernelRidge.Builder

方法

builder() → Builderstatic

创建构建器,默认 rbf(1.0) 核、alpha=1.0。

返回

新的 Builder,字段取默认值

fit(Matrix features, double[] targets) → KernelRidge

组装正则化核矩阵并用 Cholesky 求解对偶系数。

注意

Gram 矩阵为 n × n,时间 O(n²·d)、内存 O(n²)

注意

alpha 只加在 Gram 对角线上,等价于对偶问题的 L2 惩罚

参数
  • features (Matrix) – 训练特征矩阵,n 行 d 列

  • targets (double[]) – 训练目标数组,长度等于 n

返回

this,便于链式调用

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – 行数与目标长度不符,或数据含 NaN/无穷

predict(Matrix features) → double[]

用对偶系数与核值加权求和。

注意

每行需要 n 次核求值,n 为训练样本数

参数
  • features (Matrix) – 待预测特征矩阵,列数须等于训练特征数

返回

每行一个连续预测值

抛出
  • NullPointerException – features 为 null

  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

dualCoef() → double[]

返回对偶系数副本。

注意

系数与训练样本一一对应,顺序即 fit 时特征矩阵的行序

返回

长度为训练样本数的对偶系数数组副本

抛出
  • IllegalStateException – 尚未 fit

kernel() → Kernel

返回配置的核函数。

注意

核函数在构造时确定,fit 不会替换它

返回

拟合所用的 Kernel 实例;未 fit 时也可读取

kind() → ModelKind

返回模型类型标识。

返回

ModelKind.KERNEL_RIDGE

write(ModelWriter writer)

写入核函数、alpha、训练集与对偶系数。

注意

写入顺序为核函数、alpha、特征数、训练样本数、训练数据、对偶系数

参数
  • writer (ModelWriter) – 目标写入器,由调用方负责容器头与关闭

抛出
  • IllegalStateException – 尚未 fit

read(ModelReader reader) → KernelRidgestatic

从序列化流重建 KernelRidge 模型。

注意

alpha 从流中还原并重新经过 Builder 校验

参数
  • reader (ModelReader) – 已完成容器头解析的读取器

返回

可直接用于 predict 的模型实例

抛出
  • ModelFormatException – 特征数或训练样本数不为正

final class LabelEncoder implements Transformer

把类别标签双向映射为 0..k-1 整数码的编码器。

fit(double[]) 用 TreeSet 收集升序唯一值作为类别表;fit(String[]) 按字符串自然序收集,同时建立标签到下标的哈希表,并把 classes 置为 0..k-1,使数值接口与字符串接口共享同一套下标语义。

transform 对未见过的标签不做兜底:数值路径用二分查找,字符串路径查表,命中失败一律抛 IllegalArgumentException;inverseTransform 把整数码还原为类别值,浮点输入要求与最近整数相差不超过 1e-9。

示例
LabelEncoder encoder = new LabelEncoder();
double[] codes = encoder.fitTransform(new double[]{3.0, 1.0, 3.0, 2.0});
double[] original = encoder.inverseTransform(codes);
double[] classes = encoder.classes();

LabelEncoder names = new LabelEncoder();
int[] ids = names.fitTransform(new String[]{"cat", "dog", "cat"});
String[] restored = names.inverseTransformStrings(ids);

注意

fit(double[]) 与 fit(String[]) 互斥,后一次 fit 会清空另一种模式的类别表

注意

在字符串上拟合后 classes() 返回 0..k-1 的整数码,反查字符串需用 stringClasses() 或 inverseTransformStrings

注意

空输入与 null 元素在 fit 阶段即被拒绝,未知标签只在 transform 阶段报错

注意

write 把字符串按 UTF-8 逐条写入,长度前缀为字节数而非字符数

参见:basalt.ml.OneHotEncoder, basalt.ml.Transformer

构造器

LabelEncoder()

创建尚未拟合的空编码器。

注意

fit 之前调用任何 transform 或 inverseTransform 都抛 IllegalStateException

方法

fit(double[] targets) → LabelEncoder

收集升序唯一值作为类别表。

注意

类别表按数值升序排列,编码值即该顺序中的下标

注意

会清空此前 fit(String[]) 建立的字符串表

参数
  • targets (double[]) – 标签数组,不能为空,元素必须有限

返回

this,便于链式调用

抛出
  • NullPointerException – targets 为 null

  • IllegalArgumentException – targets 为空或含 NaN/无穷

fit(String[] labels) → LabelEncoder

按字符串自然序建立类别表。

注意

排序使用 String 的自然序,区分大小写,不做归一化

注意

同时把 classes 置为 0..k-1,因此数值接口在字符串拟合后仍可用

参数
  • labels (String[]) – 标签数组,不能为空,元素不能为 null

返回

this,便于链式调用

抛出
  • NullPointerException – labels 为 null,或其中某个元素为 null

  • IllegalArgumentException – labels 为空

transformToInt(double[] targets) → int[]

把标签转成整数下标。

注意

内部用 Arrays.binarySearch,依赖类别表升序

参数
  • targets (double[]) – 待编码标签

返回

与输入等长的整数码数组,取值 0..k-1

抛出
  • NullPointerException – targets 为 null

  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 出现训练时未见过的标签

transform(double[] targets) → double[]

把标签转成 double 形式的整数码。

注意

等价于 transformToInt 的逐元素 double 化

参数
  • targets (double[]) – 待编码标签

返回

与输入等长的编码数组,元素为整数值的 double

抛出
  • NullPointerException – targets 为 null

  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 出现训练时未见过的标签

fitTransform(double[] targets) → double[]

先 fit 再 transform。

注意

同一数组既作训练又作输入,因此不会出现未知标签

参数
  • targets (double[]) – 既用于拟合又用于编码的标签数组

返回

与输入等长的编码数组

抛出
  • NullPointerException – targets 为 null

  • IllegalArgumentException – targets 为空或含 NaN/无穷

inverseTransform(double[] encoded) → double[]

把浮点编码还原为类别值。

注意

先用 Math.round 取整再校验,容差 1e-9

参数
  • encoded (double[]) – 编码数组,元素须接近 [0, k-1] 内的整数

返回

与输入等长的类别值数组

抛出
  • NullPointerException – encoded 为 null

  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 下标越界,或元素与最近整数相差超过 1e-9

inverseTransform(int[] encoded) → double[]

把整数编码还原为类别值。

参数
  • encoded (int[]) – 整数码数组,元素须在 [0, k-1] 内

返回

与输入等长的类别值数组

抛出
  • NullPointerException – encoded 为 null

  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 下标越界

transform(String[] labels) → int[]

把字符串标签转成整数下标。

注意

只查表,不做大小写或空白归一化

参数
  • labels (String[]) – 待编码字符串标签

返回

与输入等长的整数码数组

抛出
  • NullPointerException – labels 为 null

  • IllegalStateException – 未在字符串标签上 fit

  • IllegalArgumentException – 出现未见过的字符串标签

fitTransform(String[] labels) → int[]

先 fit 再编码字符串标签。

参数
  • labels (String[]) – 既用于拟合又用于编码的字符串标签

返回

与输入等长的整数码数组

抛出
  • NullPointerException – labels 为 null,或其中某个元素为 null

  • IllegalArgumentException – labels 为空

inverseTransformStrings(int[] encoded) → String[]

把整数编码还原为字符串标签。

参数
  • encoded (int[]) – 整数码数组,元素须在 [0, k-1] 内

返回

与输入等长的字符串数组

抛出
  • NullPointerException – encoded 为 null

  • IllegalStateException – 未在字符串标签上 fit

  • IllegalArgumentException – 下标越界

fit(Matrix features, double[] ignoredTargets) → LabelEncoder

以单列矩阵为输入的适配方法。

注意

把矩阵数据按行展开后交给 fit(double[]),因此只接受单列输入

参数
  • features (Matrix) – 单列矩阵,每行一个标签

  • ignoredTargets (double[]) – 占位参数,被忽略,可为 null

返回

this,便于链式调用

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – features 的列数不等于 1,或数据含非有限值

transform(Matrix features) → Matrix

编码单列矩阵。

注意

内部走 transform(double[]),编码值以 double 写出

参数
  • features (Matrix) – 单列矩阵,每行一个标签

返回

行数不变、单列的编码矩阵

抛出
  • NullPointerException – features 为 null

  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不等于 1,或出现未见过的标签

inverseTransform(Matrix transformed) → Matrix

解码单列矩阵。

注意

内部走 inverseTransform(double[]),同样要求编码接近整数

参数
  • transformed (Matrix) – 单列的编码矩阵

返回

行数不变、单列的类别值矩阵

抛出
  • NullPointerException – transformed 为 null

  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不等于 1,或编码值越界

classes() → double[]

返回数值类别表副本。

返回

升序类别值副本;在字符串上拟合时为 0..k-1

抛出
  • IllegalStateException – 尚未 fit

stringClasses() → String[]

返回字符串类别表副本。

注意

不抛异常,未拟合或数值模式下一律返回 null

返回

按自然序排列的字符串类别副本;未在字符串上 fit 时为 null

kind() → ModelKind

返回模型类型标识。

返回

ModelKind.LABEL_ENCODER

write(ModelWriter writer)

写入数值类别表与可选的字符串表。

注意

先写类别数与类别值,再写字符串条数(0 表示无字符串表)

注意

每条字符串先写 UTF-8 字节数再写字节,读取端按同一格式消费

参数
  • writer (ModelWriter) – 目标写入器,由调用方负责容器头与关闭

抛出
  • IllegalStateException – 尚未 fit

read(ModelReader reader) → LabelEncoderstatic

从序列化流重建 LabelEncoder。

注意

字符串条数大于 0 时同时重建标签到下标的哈希表

参数
  • reader (ModelReader) – 已完成容器头解析的读取器

返回

可直接用于 transform 与 inverseTransform 的编码器

抛出
  • ModelFormatException – 类别数不为正

final class Lasso implements Estimator, Persistable

坐标下降求解的 L1 正则最小二乘。

fit 先令截距等于目标均值、残差为零均值化后的目标,再循环坐标下降:对每个特征计算 rho = Σ x_i·(r_i + w_j·x_i),用软阈值把 rho 向零收缩 alpha,再除以该特征的平方和得到新系数,并把变化量即时回写到残差。

每轮扫描结束后把残差均值并入截距,使残差保持零均值。alpha 作用在按行求和的尺度上(rho 与 norms 都未除以样本数),与按均方误差定义的 alpha 相差 n 倍,取值需相应放大。

示例
Matrix x = Matrix.fromRows(new double[][]{{1, 0}, {0, 1}, {1, 1}, {2, 2}});
double[] y = {1.0, 2.0, 3.0, 5.0};
Lasso lasso = Lasso.builder()
        .alpha(0.1)
        .maxIterations(500)
        .build()
        .fit(x, y);
double[] coefficients = lasso.weights();
double bias = lasso.intercept();

注意

alpha 允许为 0,此时退化为无正则的坐标下降最小二乘

注意

收敛判据是本轮坐标更新的最大绝对变化小于 tolerance;达到 maxIterations 时静默停止,不抛异常

注意

各特征的平方和只在 fit 开始时计算一次

注意

特征未中心化或标准化,列尺度直接决定收缩强度

参见:basalt.ml.Ridge, basalt.ml.LinearRegression, basalt.ml.Lasso.Builder

方法

builder() → Builderstatic

创建构建器,默认 alpha=0.1、1000 轮、1e-8。

返回

新的 Builder,字段取默认值

fit(Matrix features, double[] targets) → Lasso

用循环坐标下降拟合 L1 正则模型。

注意

系数初值全为零,相同输入的迭代轨迹完全确定

注意

平方和为零的常数列会被跳过,系数保持 0

参数
  • features (Matrix) – 训练特征矩阵,n 行 d 列

  • targets (double[]) – 训练目标数组,长度等于 n

返回

this

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – 行数与目标长度不符,或数据含 NaN/无穷

predict(Matrix features) → double[]

计算截距与系数的线性组合。

参数
  • features (Matrix) – 待预测特征矩阵,列数须等于训练特征数

返回

每行一个连续预测值

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

weights() → double[]

返回回归系数副本。

返回

长度为特征数的系数数组副本,稀疏结果中不重要的特征为 0.0

抛出
  • NullPointerException – 尚未 fit,内部数组为 null

intercept() → double

返回截距项。

注意

截距不受 L1 惩罚,每轮扫描后按残差均值修正

返回

标量截距;未 fit 时为 0.0

kind() → ModelKind

返回模型类型标识。

返回

ModelKind.LASSO

write(ModelWriter writer)

写入 alpha、迭代参数、截距与系数。

注意

写入顺序为 alpha、maxIterations、tolerance、特征数、截距、系数

参数
  • writer (ModelWriter) – 目标写入器,由调用方负责容器头与关闭

抛出
  • IllegalStateException – 尚未 fit

read(ModelReader reader) → Lassostatic

从序列化流重建 Lasso 模型。

注意

alpha、maxIterations、tolerance 从流中还原并重新经过 Builder 校验

参数
  • reader (ModelReader) – 已完成容器头解析的读取器

返回

可直接用于 predict 的模型实例

抛出
  • ModelFormatException – 特征数不为正

final class LimeExplainer

用局部加权线性代理模型解释单个预测的 LIME 解释器。

构造时统计训练数据每列的标准差(分母取样本数,标准差不超过 1e-12 的列按 1.0 处理),作为扰动的尺度。explainInstance 以目标样本为中心按 0.5 倍标准差做高斯采样:第 0 条样本固定为目标本身、权重为 1,其余样本按 w = exp(-d²/kernelWidth²) 加权,其中 d² 是采样偏移按列标准差归一化后再乘 0.5 的平方和。

代理模型是对增广设计矩阵 [1, x] 的加权岭回归,用 Cholesky 求解,特征对角加 1e-4、截距加 1e-9 的抖动。拟合优度用加权 R² 表示,即 1 减去加权残差平方和与加权总平方和之比;总平方和不超过 1e-15 时直接记为 1.0,结果下限截断为 0。

示例
Matrix train = Matrix.fromRows(new double[][]{{0, 0}, {1, 0}, {0, 1}, {1, 1}});
double[] y = {0, 0, 1, 1};
LogisticRegression model = LogisticRegression.builder().build().fit(train, y);
LimeExplainer lime = new LimeExplainer(model, train, 200, 0.75, 7L);
LimeExplainer.LocalExplanation explanation = lime.explainInstance(new double[]{1.0, 0.2});
double[] weights = explanation.featureWeights();
double fidelity = explanation.r2Fidelity();
int[] ranked = explanation.topFeatures();

注意

kernelWidth 不大于 0 时自动取 0.75·sqrt(特征数),单参数构造器即走该路径

注意

numSamples 必须不小于 20,默认 500

注意

每次调用都用 seed 重新初始化随机源,同一实例的多次解释结果完全一致

注意

topFeatures 按 |系数 × 该列标准差| 降序给出全部特征的下标,不做截断

注意

模型统一经 ShapExplainer 的求值入口调用:逻辑回归与随机森林取正类概率,直方图梯度提升取原始分数

参见:basalt.ml.ShapExplainer, basalt.ml.Estimator, basalt.ml.Pipeline

构造器

LimeExplainer(Estimator model, Matrix trainingData)

用默认采样数 500、自动核宽、种子 42 构造。

注意

等价于 new LimeExplainer(model, trainingData, 500, 0.0, 42L)

参数
  • model (Estimator) – 被解释的估计器或 Pipeline,不能为 null

  • trainingData (Matrix) – 训练数据,用于估计每列标准差

抛出
  • NullPointerException – model 或 trainingData 为 null

  • IllegalArgumentException – trainingData 含 NaN 或无穷

LimeExplainer(Estimator model, Matrix trainingData, int numSamples, double kernelWidth, long seed)

指定采样数、核宽与随机种子构造。

注意

标准差按总体口径计算,分母为样本数而非样本数减一

注意

标准差不超过 1e-12 的列按 1.0 处理,避免扰动退化为常数

参数
  • model (Estimator) – 被解释的估计器或 Pipeline,不能为 null

  • trainingData (Matrix) – 训练数据,用于估计每列标准差

  • numSamples (int) – 局部采样数,必须不小于 20

  • kernelWidth (double) – 距离核的宽度;不大于 0 时取 0.75·sqrt(特征数)

  • seed (long) – 随机种子,决定扰动样本的生成

抛出
  • NullPointerException – model 或 trainingData 为 null

  • IllegalArgumentException – trainingData 含 NaN 或无穷,或 numSamples 小于 20

方法

explainInstance(double[] instance) → LocalExplanation

为目标样本生成局部解释。

注意

localPrediction 由代理模型在目标样本上求值,与 modelPrediction 的差异反映代理拟合质量

注意

全部扰动样本的预测通过一次批量调用完成,不逐行调用

参数
  • instance (double[]) – 目标样本,长度须等于训练特征数

返回

含截距、各特征权重、局部与真实预测、加权 R² 与特征排序的 LocalExplanation

抛出
  • NullPointerException – instance 为 null

  • IllegalArgumentException – instance 长度与训练特征数不符

final class LinearRegression implements Estimator, Persistable

全批量梯度下降的普通最小二乘。

fit 从全零权重与零截距出发,每个 epoch 用全部样本累加 MSE 梯度(缩放因子 2/n),加上 2·l2·w 后按 learningRate 做一次整批更新;fitIntercept 为 true 时截距同步更新,且不受 l2 惩罚。

lossHistory 记录每个 epoch 更新前算出的均方误差,可用于判断是否收敛。算法对特征尺度敏感:未标准化时应降低 learningRate,否则梯度下降可能震荡或发散。

示例
Matrix x = Matrix.fromRows(new double[][]{{0, 1}, {1, 1}, {2, 1}, {3, 1}});
double[] y = {1.0, 3.0, 5.0, 7.0};
LinearRegression model = LinearRegression.builder()
        .learningRate(0.05)
        .epochs(2000)
        .fitIntercept(true)
        .build()
        .fit(x, y);
double[] predictions = model.predict(x);
double one = model.predictOne(new double[]{4.0, 1.0}, 0);

注意

权重初值恒为零,同一输入的拟合结果完全确定

注意

l2 以 2·l2·w 加入梯度,只作用于权重

注意

不对特征做中心化或标准化,也不做特征筛选

参见:basalt.ml.Ridge, basalt.ml.LogisticRegression, basalt.ml.LinearRegression.Builder

方法

builder() → Builderstatic

创建构建器,默认 lr=0.05、2000 轮、无正则。

返回

新的 Builder,字段取默认值

fit(Matrix features, double[] targets) → LinearRegression

用全批量梯度下降最小化均方误差。

注意

epochs 轮内不做提前停止,lossHistory 长度恒为 epochs

参数
  • features (Matrix) – 训练特征矩阵,n 行 d 列

  • targets (double[]) – 训练目标数组,长度等于 n

返回

this

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – 行数与目标长度不符,或数据含 NaN/无穷

predict(Matrix features) → double[]

批量计算线性预测值。

参数
  • features (Matrix) – 待预测特征矩阵,列数须等于训练特征数

返回

长度等于行数的连续预测值

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

predictOne(double[] features, int offset) → double

对扁平数组中的单个样本预测。

适合在已经展开的批量缓冲区上按偏移逐行调用,避免为单行构造 Matrix。

注意

只检查长度,不检查取值是否有限

参数
  • features (double[]) – 扁平特征数组

  • offset (int) – 该样本第一个特征在数组中的下标

返回

单样本的预测值

抛出
  • IllegalStateException – 尚未 fit

  • IndexOutOfBoundsException – offset 为负,或 offset 加特征数超过数组长度

weights() → double[]

返回权重副本。

注意

返回副本,修改它不影响模型

返回

长度为特征数的权重副本;未 fit 时返回空数组

intercept() → double

返回截距项。

注意

fitIntercept 为 false 时该值恒为 0.0

返回

标量截距;未 fit 时为 0.0

lossHistory() → double[]

返回每个 epoch 的均方误差。

注意

返回副本;未 fit 时为空数组

注意

曲线单调下降说明学习率合适,震荡说明步长偏大

返回

长度为 epochs 的数组,元素是当轮更新前的 MSE

kind() → ModelKind

返回模型类型标识。

返回

ModelKind.LINEAR_REGRESSION

write(ModelWriter writer)

写入超参数、截距与权重。

注意

写入顺序为 learningRate、epochs、l2、fitIntercept 字节、特征数、截距、权重

注意

lossHistory 不写入流,read 后为空数组

参数
  • writer (ModelWriter) – 目标写入器,由调用方负责容器头与关闭

抛出
  • IllegalStateException – 尚未 fit

read(ModelReader reader) → LinearRegressionstatic

从序列化流重建 LinearRegression 模型。

注意

超参数从流中还原并重新经过 Builder 校验

注意

lossHistory 为空数组,训练曲线不可恢复

参数
  • reader (ModelReader) – 已完成容器头解析的读取器

返回

已标记为拟合状态、可直接 predict 的实例

抛出
  • ModelFormatException – 特征数不为正

final class LinearSVM implements Estimator, Persistable

PEGASOS 次梯度法训练的二分类线性 SVM。

fit 要求标签恰好取两个不同值,按升序映射为负类与正类(较大者记 +1)。每个 epoch 先洗牌样本顺序,再逐样本判断 margin:小于 1 时做 hinge 更新 w ← (1-ηλ)w + η·y·x、b ← b + η·y,否则只做收缩 w ← (1-ηλ)w。

步长 η = 1/(λ·t),t 是跨 epoch 累计的样本计数,因此收缩因子 1-ηλ 等于 1-1/t。偏置只累加 η·y,不受 L2 正则。predict 取 w·x + b 的符号,返回原始标签值而非 ±1。

示例
Matrix x = Matrix.fromRows(new double[][]{{0, 0}, {0, 1}, {1, 0}, {1, 1}});
double[] y = {0, 0, 1, 1};
LinearSVM svm = LinearSVM.builder()
        .lambda(0.01)
        .epochs(20)
        .seed(42L)
        .build()
        .fit(x, y);
double[] labels = svm.predict(x);
double[] w = svm.weights();
double b = svm.bias();

注意

lambda 越小正则越弱、早期有效步长越大

注意

洗牌由 seed 驱动的 Random 完成,默认 42,结果可复现

注意

单类别或三分类以上的数据会在 fit 时被拒绝

注意

目标值只用于确定两个类别,不做 0/1 之外的假设

参见:basalt.ml.LogisticRegression, basalt.ml.LinearSVM.Builder

方法

builder() → Builderstatic

创建构建器,默认 lambda=0.01、20 轮、种子 42。

返回

新的 Builder,字段取默认值

fit(Matrix features, double[] targets) → LinearSVM

用 PEGASOS 迭代训练二分类线性模型。

注意

类别按升序决定符号:较大值为正类

注意

每轮重新洗牌,累计步数 t 不随 epoch 重置

参数
  • features (Matrix) – 训练特征矩阵,n 行 d 列

  • targets (double[]) – 训练标签,必须恰好包含两个不同取值

返回

this

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – 类别数不等于 2,或形状不符、数据含非有限值

predict(Matrix features) → double[]

按判别值的符号输出原始标签。

注意

判别值恰为 0 时判为正类

参数
  • features (Matrix) – 待预测特征矩阵,列数须等于训练特征数

返回

每行一个训练集中出现过的标签值

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

weights() → double[]

返回权重向量副本。

返回

长度为特征数的权重副本

抛出
  • NullPointerException – 尚未 fit,内部数组为 null

bias() → double

返回偏置项。

注意

偏置不参与正则化,只按 η·y 累加

返回

标量偏置 b;未 fit 时为 0.0

classes() → double[]

返回两个类别值。

注意

下标 0 为负类、1 为正类,判别值非负时输出下标 1

注意

不抛异常,未拟合时返回 null

返回

升序排列的两个类别副本;未 fit 时为 null

kind() → ModelKind

返回模型类型标识。

返回

ModelKind.LINEAR_SVM

write(ModelWriter writer)

写入超参数、偏置、类别与权重。

注意

写入顺序为 lambda、epochs、seed、特征数、bias、classes、weights

参数
  • writer (ModelWriter) – 目标写入器,由调用方负责容器头与关闭

抛出
  • IllegalStateException – 尚未 fit

read(ModelReader reader) → LinearSVMstatic

从序列化流重建 LinearSVM 模型。

注意

类别数组固定按 2 个元素读取

注意

lambda、epochs、seed 从流中还原并重新经过 Builder 校验

参数
  • reader (ModelReader) – 已完成容器头解析的读取器

返回

可直接用于 predict 的模型实例

抛出
  • ModelFormatException – 特征数不为正

final class LogisticRegression implements Estimator, Persistable

全批量梯度下降的二分类逻辑回归。

fit 要求标签严格等于 0.0 或 1.0,其他取值直接拒绝。每个 epoch 用全部样本计算交叉熵梯度;损失按 max(z,0) - z·y + log1p(exp(-|z|)) 计算,在 logit 绝对值很大时也不会溢出。

l2 以 2·l2·w 加入权重梯度,截距不受惩罚。predictProbability 用分段 sigmoid 输出概率,predict 再以固定阈值 0.5 转成 0/1 硬标签。

示例
Matrix x = Matrix.fromRows(new double[][]{{0, 0}, {0, 1}, {1, 0}, {1, 1}});
double[] y = {0, 0, 1, 1};
LogisticRegression model = LogisticRegression.builder()
        .learningRate(0.1)
        .epochs(2000)
        .build()
        .fit(x, y);
double[] probability = model.predictProbability(x);
double[] labels = model.predict(x);

注意

概率阈值硬编码为 0.5,不可配置

注意

特征未标准化时需按尺度调整 learningRate

注意

类别必须是 0 与 1,不做任意标签的自动映射

参见:basalt.ml.LinearSVM, basalt.ml.Metrics, basalt.ml.LogisticRegression.Builder

方法

builder() → Builderstatic

创建构建器,默认 lr=0.1、2000 轮、无正则。

返回

新的 Builder,字段取默认值

fit(Matrix features, double[] targets) → LogisticRegression

用全批量梯度下降最小化交叉熵。

注意

标签校验在形状校验之后进行,逐元素扫描

参数
  • features (Matrix) – 训练特征矩阵,n 行 d 列

  • targets (double[]) – 训练标签,每个元素必须是 0.0 或 1.0

返回

this

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – 标签不是 0/1,或行数与标签长度不符、数据含非有限值

predictProbability(Matrix features) → double[]

输出每行属于正类的概率。

参数
  • features (Matrix) – 待预测特征矩阵,列数须等于训练特征数

返回

长度等于行数的概率数组,取值在 [0,1]

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

predict(Matrix features) → double[]

以 0.5 为阈值输出 0/1 标签。

注意

内部先算概率再阈值化,与 predictProbability 结果一致

参数
  • features (Matrix) – 待预测特征矩阵

返回

每行 1.0 或 0.0,概率大于等于 0.5 判为 1.0

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

lossHistory() → double[]

返回每个 epoch 的平均交叉熵。

注意

返回副本;未 fit 时为空数组

返回

长度为 epochs 的数组,元素是当轮更新前的平均损失

weights() → double[]

返回权重副本。

注意

返回副本,修改它不影响模型

返回

长度为特征数的权重副本;未 fit 时返回空数组

intercept() → double

返回截距项。

注意

截距不受 l2 惩罚,只按平均梯度更新

返回

标量截距;未 fit 时为 0.0

kind() → ModelKind

返回模型类型标识。

返回

ModelKind.LOGISTIC_REGRESSION

write(ModelWriter writer)

写入超参数、截距与权重。

注意

写入顺序为 learningRate、epochs、l2、特征数、截距、权重

注意

lossHistory 不写入流,read 后为空数组

参数
  • writer (ModelWriter) – 目标写入器,由调用方负责容器头与关闭

抛出
  • IllegalStateException – 尚未 fit

read(ModelReader reader) → LogisticRegressionstatic

从序列化流重建 LogisticRegression 模型。

注意

超参数从流中还原并重新经过 Builder 校验

注意

lossHistory 为空数组,训练曲线不可恢复

参数
  • reader (ModelReader) – 已完成容器头解析的读取器

返回

已标记为拟合状态、可直接 predict 的实例

抛出
  • ModelFormatException – 特征数不为正

final class Metrics

分类与回归指标,纯 Java 实现。

全部方法为静态方法,输入是两个等长 double[];长度不等或为空时抛 IllegalArgumentException。分类指标按 double 精确相等比较标签,因此预测必须是类别码(例如 0/1),传入概率会得到无意义的结果。

precision、recall、f1 用 positive 参数指定正类,分母为零时返回 0.0 而不是 NaN。rocAuc 单独约定输入:标签必须只含 0/1,分数可以是任意实数,采用并列取平均秩的 Mann-Whitney 统计量,等价于梯形法 ROC 面积。

示例
double[] expected = {1, 0, 1, 1, 0};
double[] predicted = {1, 0, 0, 1, 0};
double accuracy = Metrics.accuracy(expected, predicted);
double f1 = Metrics.f1(expected, predicted, 1.0);
int[][] matrix = Metrics.confusionMatrix(expected, predicted);
double auc = Metrics.rocAuc(expected, new double[]{0.9, 0.1, 0.4, 0.8, 0.2});

注意

不修改输入数组

注意

macroF1 与 confusionMatrix 的类别集合取自 expected 的升序唯一值

注意

回归指标不做样本数之外的归一化,量纲随目标值

参见:basalt.ml.Estimators.Metric, basalt.ml.Estimator

方法

accuracy(double[] expected, double[] predicted) → doublestatic

预测与期望完全相等的比例。

注意

用 == 比较 double,浮点近似值不会被判为相等

参数
  • expected (double[]) – 真实标签

  • predicted (double[]) – 预测标签,长度须与 expected 相同

返回

[0,1] 的准确率,即相等元素数除以样本数

抛出
  • IllegalArgumentException – 两个数组长度不一致或为空

precision(double[] expected, double[] predicted, double positive) → doublestatic

指定正类的精确率。

参数
  • expected (double[]) – 真实标签

  • predicted (double[]) – 预测标签

  • positive (double) – 被视为正类的标签值

返回

TP/(TP+FP);没有任何预测为正类时返回 0.0

抛出
  • IllegalArgumentException – 两个数组长度不一致或为空

recall(double[] expected, double[] predicted, double positive) → doublestatic

指定正类的召回率。

参数
  • expected (double[]) – 真实标签

  • predicted (double[]) – 预测标签

  • positive (double) – 被视为正类的标签值

返回

TP/(TP+FN);expected 中没有正类时返回 0.0

抛出
  • IllegalArgumentException – 两个数组长度不一致或为空

f1(double[] expected, double[] predicted, double positive) → doublestatic

精确率与召回率的调和平均。

参数
  • expected (double[]) – 真实标签

  • predicted (double[]) – 预测标签

  • positive (double) – 被视为正类的标签值

返回

2PR/(P+R);P 与 R 同时为 0 时返回 0.0

抛出
  • IllegalArgumentException – 两个数组长度不一致或为空

macroF1(double[] expected, double[] predicted) → doublestatic

按类别取 F1 的算术平均。

类别集合来自 expected 的升序唯一值,对每个类别分别作为正类计算 F1,再求平均。多分类问题常用该指标,可避免多数类主导。

注意

predicted 中若出现 expected 之外的新标签,不会被单独计为一类

参数
  • expected (double[]) – 真实标签,决定类别集合

  • predicted (double[]) – 预测标签

返回

[0,1] 的宏平均 F1

抛出
  • IllegalArgumentException – 两个数组长度不一致或为空

confusionMatrix(double[] expected, double[] predicted) → int[][]static

返回以类别为行列的混淆矩阵。

行对应真实类别,列对应预测类别,行列顺序都是 expected 唯一值的升序,因此 matrix[i][j] 表示真实为第 i 类且被预测为第 j 类的样本数。

注意

对角线元素之和等于 accuracy 的分子

参数
  • expected (double[]) – 真实标签,决定矩阵维度与类别顺序

  • predicted (double[]) – 预测标签

返回

k×k 的 int 矩阵,k 为 expected 的唯一值个数

抛出
  • IllegalArgumentException – predicted 含 expected 之外的类别,或两数组长度不一致、为空

rocAuc(double[] labels, double[] scores) → doublestatic

二分类 ROC 曲线下面积。

先按分数升序排序并给出秩,同分样本取平均秩,再用正类秩和减去 positives·(positives+1)/2 得到 U 统计量,最后除以 positives·negatives。

注意

并列分数按平均秩处理,结果与样本顺序无关

注意

只支持二分类;多分类需先做 one-vs-rest 拆分

参数
  • labels (double[]) – 真实标签,必须只含 0.0 与 1.0,其中 1 为正类

  • scores (double[]) – 实数打分,越大越倾向正类,可以是 logit 或概率

返回

[0,1] 的 AUC,0.5 相当于随机排序

抛出
  • IllegalArgumentException – 标签含 0/1 之外的值、缺少某一类,或两数组长度不一致、为空

mse(double[] expected, double[] predicted) → doublestatic

均方误差。

参数
  • expected (double[]) – 真实值

  • predicted (double[]) – 预测值

返回

Σ(expected-predicted)²/n,非负

抛出
  • IllegalArgumentException – 两个数组长度不一致或为空

rmse(double[] expected, double[] predicted) → doublestatic

均方根误差。

注意

门面 crossValidate 会对其取负号,使指标统一为越大越好

参数
  • expected (double[]) – 真实值

  • predicted (double[]) – 预测值

返回

mse 的平方根,与目标值同量纲

抛出
  • IllegalArgumentException – 两个数组长度不一致或为空

mae(double[] expected, double[] predicted) → doublestatic

平均绝对误差。

参数
  • expected (double[]) – 真实值

  • predicted (double[]) – 预测值

返回

Σ|expected-predicted|/n,非负

抛出
  • IllegalArgumentException – 两个数组长度不一致或为空

r2(double[] expected, double[] predicted) → doublestatic

决定系数。

以 expected 的均值为基准计算总平方和,返回 1 - SSres/SStot;模型比常数均值预测更差时结果为负。

注意

SStot 为 0(所有真实值相同)时:残差也为 0 返回 1.0,否则返回 0.0

参数
  • expected (double[]) – 真实值

  • predicted (double[]) – 预测值

返回

1 - SSres/SStot,上界为 1,可以为负

抛出
  • IllegalArgumentException – 两个数组长度不一致或为空

final class MinMaxScaler implements Transformer, Estimator

按列线性映射到指定区间的缩放器。

fit 逐列扫描得到最小值与最大值,dataRange 记录极差,scale = (featureMax - featureMin) / dataRange,minOffset = featureMin - dataMin·scale;transform 计算 v·scale + minOffset,inverseTransform 用 (v - minOffset) / scale 还原。

极差不超过 1e-12 的常数列把缩放分母取 1.0,此时 scale 等于目标区间宽度、输出恒为 featureMin,不会产生除零或 NaN。clip 为 true 时 transform 的输出被截断到 [featureMin, featureMax],对训练分布之外的值同样生效。

示例
Matrix x = Matrix.fromRows(new double[][]{{1, 10}, {2, 20}, {3, 30}});
MinMaxScaler scaler = MinMaxScaler.builder()
        .featureRange(-1.0, 1.0)
        .clip(true)
        .build()
        .fit(x);
Matrix scaled = scaler.transform(x);
Matrix restored = scaler.inverseTransform(scaled);
double[] scale = scaler.scale();

注意

目标区间默认 [0, 1],由 Builder.featureRange(min, max) 设置,要求有限且 min < max

注意

拟合统计量 dataMin、dataMax、dataRange、scale、minOffset 随模型一起序列化

注意

transform 与 inverseTransform 都要求列数等于拟合时的特征数

注意

inverseTransform 只做逆线性映射,clip 造成的截断无法还原

注意

同时实现 Transformer 与 Estimator,可放入 Pipeline

参见:basalt.ml.StandardScaler, basalt.ml.Transformer, basalt.ml.MinMaxScaler.Builder

方法

builder() → Builderstatic

创建构建器,默认区间 [0, 1]、不截断。

返回

新的 Builder,字段取默认值

fit(Matrix features) → MinMaxScaler

只用特征拟合,目标数组缺省为 null。

注意

等价于 fit(features, null)

参数
  • features (Matrix) – 训练特征矩阵,行是样本、列是特征

返回

this,便于链式调用

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – features 含 NaN 或无穷

fit(Matrix features, double[] ignoredTargets) → MinMaxScaler

逐列统计极值并算出缩放系数。

注意

单次扫描,时间 O(n·d)

注意

常数列的 dataRange 记为 0,但缩放分母取 1.0

参数
  • features (Matrix) – 训练特征矩阵,行是样本、列是特征

  • ignoredTargets (double[]) – 占位参数;缩放忽略监督目标,可为 null

返回

this,便于链式调用

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – features 含 NaN 或无穷

transform(Matrix features) → Matrix

按列线性映射到目标区间。

注意

clip 为 true 时输出被截断到 [featureMin, featureMax]

参数
  • features (Matrix) – 待变换特征矩阵,列数须等于拟合特征数

返回

与输入同形状的变换结果

抛出
  • NullPointerException – features 为 null

  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

inverseTransform(Matrix transformed) → Matrix

把缩放结果还原到原始量纲。

注意

按 (v - minOffset) / scale 逐元素计算,scale 恒为正

参数
  • transformed (Matrix) – 变换后的矩阵,列数须等于拟合特征数

返回

与输入同形状的还原结果

抛出
  • NullPointerException – transformed 为 null

  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

predict(Matrix features) → double[]

返回变换结果的扁平数组。

注意

等价于 transform(features).toArray(),clip 同样生效

参数
  • features (Matrix) – 待变换特征矩阵,列数须等于拟合特征数

返回

长度为 行数 × 特征数 的数组

抛出
  • NullPointerException – features 为 null

  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

dataMin() → double[]

返回拟合时各列最小值。

返回

长度等于特征数的数组副本

抛出
  • IllegalStateException – 尚未 fit

dataMax() → double[]

返回拟合时各列最大值。

返回

长度等于特征数的数组副本

抛出
  • IllegalStateException – 尚未 fit

dataRange() → double[]

返回各列极差。

返回

dataMax - dataMin 的数组副本;常数列为 0

抛出
  • IllegalStateException – 尚未 fit

scale() → double[]

返回各列缩放系数。

注意

反变换需要除以该系数,因此它恒为正

返回

目标区间宽度与极差之比的数组副本;常数列等于区间宽度

抛出
  • IllegalStateException – 尚未 fit

kind() → ModelKind

返回模型类型标识。

返回

ModelKind.MIN_MAX_SCALER

write(ModelWriter writer)

写入目标区间、截断标志与全部拟合统计量。

注意

写入顺序为区间下界、上界、clip 字节、特征数、dataMin、dataMax、dataRange、scale、minOffset

注意

minOffset 一并写入,读取端无需重新推导

参数
  • writer (ModelWriter) – 目标写入器,由调用方负责容器头与关闭

抛出
  • IllegalStateException – 尚未 fit

read(ModelReader reader) → MinMaxScalerstatic

从序列化流重建 MinMaxScaler。

注意

统计量直接读取,不重新扫描数据

参数
  • reader (ModelReader) – 已完成容器头解析的读取器

返回

可直接用于 transform 与 inverseTransform 的实例

抛出
  • ModelFormatException – 特征数不为正,或区间上界不大于下界

final class OneHotEncoder implements Transformer, Estimator

把类别列展开为稠密 0/1 指示特征的编码器。

fit 对每个被标记为类别的列收集升序唯一值作为词表,并预先计算输出列偏移;未被指定的列原样透传,各占一个输出列。categoricalColumns 未设置时全部列都按类别处理。

transform 在每个类别块内把命中的位置置 1、其余为 0;handleUnknown 为 ERROR 时遇到词表外的值抛异常,为 IGNORE 时该样本的整块保持全 0。inverseTransform 对每个类别块取最大值的下标还原类别值,整块为 0 时输出 NaN。

示例
Matrix x = Matrix.fromRows(new double[][]{
    {0, 1.5}, {1, 2.5}, {2, 3.5}
});
OneHotEncoder encoder = OneHotEncoder.builder()
        .categoricalColumns(0)
        .handleUnknown(OneHotEncoder.HandleUnknown.IGNORE)
        .build()
        .fit(x);
Matrix encoded = encoder.transform(x);
int width = encoder.outputFeatureCount();
Matrix back = encoder.inverseTransform(encoded);

注意

handleUnknown 默认 ERROR,可在 Builder 中改为 IGNORE

注意

词表按 double 升序排列,比较用 Double.compare,因此 -0.0 与 0.0 被视为不同类别

注意

输出特征数等于各列词表长度之和,数值列按 1 计

注意

inverseTransform 只取 argmax,不校验输入是否为合法 one-hot

注意

类别词表与列偏移随模型一起序列化

参见:basalt.ml.LabelEncoder, basalt.ml.KBinsDiscretizer, basalt.ml.OneHotEncoder.Builder

方法

builder() → Builderstatic

创建构建器,默认全部列编码、未知类别报错。

返回

新的 Builder,字段取默认值

fit(Matrix features) → OneHotEncoder

只用特征拟合,目标数组缺省为 null。

注意

等价于 fit(features, null)

参数
  • features (Matrix) – 训练特征矩阵,行是样本、列是特征

返回

this,便于链式调用

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – features 含 NaN 或无穷,或类别列下标越界

fit(Matrix features, double[] ignoredTargets) → OneHotEncoder

收集每列的类别词表并计算输出布局。

注意

每个类别列做一次 TreeSet 收集,时间 O(n·d·log n)

注意

categoricalColumns 未设置时全部列按类别处理,数值列需显式排除

参数
  • features (Matrix) – 训练特征矩阵,n 行 d 列

  • ignoredTargets (double[]) – 占位参数;编码忽略监督目标,可为 null

返回

this,便于链式调用

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – features 含 NaN 或无穷,或 categoricalColumns 中的下标越界

transform(Matrix features) → Matrix

把类别列展开为 0/1 指示特征。

注意

数值列按原值透传,不做缩放或中心化

参数
  • features (Matrix) – 待编码矩阵,列数须等于拟合特征数

返回

行数不变、宽度为 outputFeatureCount() 的稠密矩阵

抛出
  • NullPointerException – features 为 null

  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配、含非有限值,或 handleUnknown 为 ERROR 时出现未知类别

inverseTransform(Matrix transformed) → Matrix

从指示特征还原原始列。

注意

每个类别块取最大值对应的下标;整块不大于 0 时该格输出 NaN

参数
  • transformed (Matrix) – 编码后的矩阵,列数须等于输出特征数

返回

行数不变、宽度等于输入特征数的矩阵

抛出
  • NullPointerException – transformed 为 null

  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

predict(Matrix features) → double[]

返回编码结果的扁平数组。

注意

等价于 transform(features).toArray()

参数
  • features (Matrix) – 待编码矩阵,列数须等于拟合特征数

返回

长度为 行数 × 输出特征数 的数组

抛出
  • NullPointerException – features 为 null

  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配、含非有限值,或出现未知类别

categories() → double[][]

返回每列的类别词表。

注意

每个子数组按升序排列,且为深拷贝

返回

长度为输入特征数的二维数组副本;数值列为空数组

抛出
  • IllegalStateException – 尚未 fit

outputFeatureCount() → int

返回编码后的特征宽度。

注意

等于各列词表长度之和,数值列按 1 计

注意

不抛异常,可在拟合前查询(此时为 0)

返回

输出列数;未 fit 时为 0

kind() → ModelKind

返回模型类型标识。

返回

ModelKind.ONE_HOT_ENCODER

write(ModelWriter writer)

写入未知类别策略、特征数与逐列词表。

注意

每列依次写类别标志字节、词表长度与词表值,最后写 outputOffsets

注意

输入与输出特征数在词表之前写出,读取端可先分配空间

参数
  • writer (ModelWriter) – 目标写入器,由调用方负责容器头与关闭

抛出
  • IllegalStateException – 尚未 fit

read(ModelReader reader) → OneHotEncoderstatic

从序列化流重建 OneHotEncoder。

注意

categoricalColumns 的原始配置不被保留,分类标志来自逐列写出的字节

参数
  • reader (ModelReader) – 已完成容器头解析的读取器

返回

可直接用于 transform 与 inverseTransform 的编码器

抛出
  • ModelFormatException – HandleUnknown 序数非法,或输入/输出特征数不为正

final class PCA implements Estimator, Transformer, Persistable

中心化主成分分析,含协方差与 Gram 两条精确路径。

JACOBI 路径分解 p × p 协方差矩阵,代价为 O(n p²) 的协方差累加加若干次 Jacobi 扫描,适合 n ≫ p。GRAM 路径分解 n × n Gram 矩阵,再用 v = Xᵀu / ‖Xᵀu‖ 还原主方向,代价 O(n² p),适合 p > n 的宽表。

两条路径都输出正交归一的主方向与协方差尺度上的方差,结果在符号与数值误差范围内一致。主方向的符号按绝对值最大的分量为正固定,因此重复拟合可复现。

示例
Matrix features = Matrix.fromRows(new double[][] {
    {2.5, 2.4}, {0.5, 0.7}, {2.2, 2.9},
    {1.9, 2.2}, {3.1, 3.0}, {2.3, 2.7}
});
PCA pca = PCA.builder()
        .components(1)
        .solver(EigenSolver.AUTO)
        .whiten(true)
        .build()
        .fit(features);
Matrix projected = pca.transform(features);
Matrix restored = pca.inverseTransform(projected);
double[] ratio = pca.explainedVarianceRatio();

注意

AUTO 在特征数大于样本数且样本数不超过 20000 时选 GRAM,否则选 JACOBI

注意

解释方差比的分母是全部 p 个特征方差之和,而非所选分量方差之和,因此前 k 个比值相加通常小于 1

注意

Gram 路径需要 n × n 的双精度矩阵,20000 样本即约 3.2 GB

注意

Jacobi 扫描以相对非对角范数判定收敛,收敛判据与矩阵整体尺度无关

参见:basalt.ml.EigenSolver, basalt.ml.Estimator, basalt.core.Persistable

方法

builder() → Builderstatic

创建 PCA 构建器。

返回

参数取默认值的新 Builder 实例

fit(Matrix features) → PCA

只用特征拟合,目标数组缺省为 null。

参数
  • features (Matrix) – 训练样本矩阵,行是样本、列是特征

返回

this,便于链式调用

fit(Matrix features, double[] ignoredTargets) → PCA

中心化后做特征分解并保留前若干主成分。

先按列求均值并中心化,再按解析出的求解器计算特征分解;特征值截断为非负、按降序排序,保留前 components 个方向,总方差始终按全部特征累计。

参数
  • features (Matrix) – 训练样本矩阵,行是样本、列是特征;元素必须有限

  • ignoredTargets (double[]) – 占位参数;降维忽略监督目标,可为 null

返回

this,便于链式调用

抛出
  • IllegalArgumentException – features 为 null 或含非有限值;样本数小于 2;components 大于 min(样本数, 特征数);显式选择 GRAM 而样本数超过 20000

transform(Matrix features) → Matrix

把样本投影到主成分坐标。

逐样本减去训练均值后与各主方向做点积。whiten 为 true 时每个投影再除以其主成分标准差 sqrt(max(特征值, 1e-12)),使各分量方差为 1。

参数
  • features (Matrix) – 样本矩阵,列数须与拟合时一致

返回

样本数 × components 的投影矩阵

抛出
  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 特征列数与拟合时不一致

inverseTransform(Matrix transformed) → Matrix

把主成分坐标重建回原始特征空间。

先按主方向加权求和,再加回均值。白化模型会先把每个坐标乘回对应标准差,因此与 transform 互为逆变换(截断维度时是到子空间的正交投影)。

参数
  • transformed (Matrix) – 样本数 × components 的投影矩阵,列数须等于 components

返回

样本数 × 特征数 的重建矩阵

抛出
  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – transformed 的列数不等于 components

predict(Matrix features) → double[]

返回投影结果的扁平数组。

等价于 transform(features).toArray(),按行优先展开,便于接入只需要 double[] 的下游流程。

参数
  • features (Matrix) – 样本矩阵,列数须与拟合时一致

返回

长度为 样本数 × components 的数组

抛出
  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 特征列数与拟合时不一致

explainedVariance() → double[]

返回各主成分的方差。

数值为协方差矩阵的特征值,已截断为非负,按降序排列,单位是原始特征的方差单位。内部数组在 fit 阶段分配,未拟合时不可调用。

返回

长度等于 components 的数组副本

explainedVarianceRatio() → double[]

返回各主成分方差占总方差的比例。

分母是全部 p 个特征的方差之和,与保留的分量数无关,因此前 k 个比值之和通常小于 1。总方差不为正(例如全部特征为常数)时返回全 0。

返回

长度等于 components 的数组

components() → Matrix

返回主方向矩阵。

注意

每行已归一化为单位长度,且绝对值最大的分量被固定为正号

注意

特征值过小、方向无法还原时该行全为 0

返回

components × 特征数 的矩阵,每行一个单位长度的主方向

抛出
  • IllegalStateException – 尚未拟合

means() → double[]

返回拟合时各特征的均值。

注意

未拟合时内部均值为 null,调用会抛 NullPointerException

返回

长度等于特征数的数组副本

solver() → EigenSolver

返回实际使用的求解器。

返回

AUTO 解析后的具体求解器;未拟合时为 null,由 read 重建的模型为 JACOBI

kind() → ModelKind

返回模型类型标识。

返回

ModelKind.PCA

write(ModelWriter writer)

写入分量数、特征数、白化标志、总方差、均值、特征值与主方向。

注意

tolerance 与 maxIterations 不写入流,read 后回到 Builder 默认值

参数
  • writer (ModelWriter) – 目标写入器,由调用方负责容器头与关闭

抛出
  • IllegalStateException – 尚未拟合

read(ModelReader reader) → PCAstatic

从序列化流重建 PCA 模型。

注意

solver() 固定返回 JACOBI,原始求解器选择不被保留

参数
  • reader (ModelReader) – 已完成容器头解析的读取器

返回

可直接用于 transform 与 inverseTransform 的模型实例

抛出
  • ModelFormatException – 分量数或特征数不为正,或白化标志不是 0/1

final class Pipeline implements Estimator, Transformer, Persistable

顺序串联预处理步骤与最终估计器的管道

fit 按声明顺序对每一步调用 fitTransform:该步先用当前矩阵拟合自身参数,再把同一份矩阵变换后交给下一步;挂了最终估计器时,用最后一步的输出与原始 targets 拟合该估计器。transform 与 predict 只调用各步的 transform,不会重新估计任何参数。

predict 先依次 transform 全部步骤,再交给最终估计器;未挂估计器但最后一步本身实现了 Estimator 时,直接把原始 features 交给该步的 predict,不再经过前面各步的变换。transform 在最终估计器也实现 Transformer 时会额外对它做一次变换,因此同一类型既能表达纯预处理管道,也能表达带输出变换的完整链路。

序列化先写步骤数,再对每步写名称、类型码、负载长度与负载,随后写一个字节标记是否存在最终估计器;存在时再写名称、类型码与负载。read 按类型码把每段负载交回 ModelCodec.readPayload 解码,因此预处理统计量与估计器权重在 .bsl 中是单个原子对象,加载后无需重新拟合。

示例
Matrix x = Matrix.fromRows(new double[][]{
        {1.0, Double.NaN}, {2.0, 3.0}, {3.0, 4.0}, {4.0, 5.5}});
double[] y = {1.0, 2.0, 3.0, 4.0};

Pipeline pipeline = Pipeline.builder()
        .addStep("impute", SimpleImputer.builder()
                .strategy(SimpleImputer.Strategy.MEAN).build())
        .addStep("scale", StandardScaler.builder().build())
        .estimator("ridge", Ridge.builder().alpha(0.5).build())
        .build()
        .fit(x, y);

double[] predictions = pipeline.predict(x);
Matrix transformed = pipeline.transform(x);

Path file = Path.of("pipeline.bsl");
ModelCodec.save(file, pipeline);
Pipeline restored = ModelCodec.load(file, Pipeline.class);

注意

构建时至少要有一个步骤或一个最终估计器,否则 build() 抛 IllegalArgumentException

注意

最终估计器必须实现 Persistable,否则 write 抛 IllegalStateException

注意

步骤名重复时 namedSteps() 中后写入者覆盖先写入者

注意

read 把步骤数限制在 [0, 10000],单个字符串长度限制在 [0, 65536] 字节

参见:basalt.ml.Transformer, basalt.ml.Estimator, basalt.ml.Pipeline.Step, basalt.io.ModelCodec

方法

builder() → Builderstatic

创建管道构建器

返回

新的 Builder,初始无步骤、无估计器

fit(Matrix features) → Pipeline

无监督拟合,等价于 targets 为 null

注意

需要目标值的步骤(如 SelectKBest)在此重载下会因 targets 为 null 抛 NullPointerException

参数
  • features (Matrix) – 训练特征矩阵

返回

this

抛出
  • NullPointerException – features 为 null

fit(Matrix features, double[] targets) → Pipeline

逐步 fitTransform 后拟合最终估计器

每一步用当前矩阵调用 fitTransform,把输出作为下一步的输入;targets 原样传给每一步与最终估计器,最终估计器用最后一步的输出拟合。

注意

中间矩阵逐级替换,管道不保留各步的中间结果

参数
  • features (Matrix) – 训练特征矩阵,行数为样本数

  • targets (double[]) – 训练目标数组,长度须等于行数;无监督步骤可忽略

返回

this,各步与估计器均已完成拟合

抛出
  • NullPointerException – features 为 null

transform(Matrix features) → Matrix

按顺序应用各步 transform,不重新拟合

若最终估计器实现 Transformer,还会再对它做一次 transform。

参数
  • features (Matrix) – 待变换特征矩阵,列数须与首步期望一致

返回

变换后的矩阵,列数由最后一步决定

抛出
  • NullPointerException – features 为 null

  • IllegalStateException – 任一步尚未拟合

  • IllegalArgumentException – 列数与某步期望不一致或含非有限值

inverseTransform(Matrix transformed) → Matrix

逆序还原各步变换

先对最终估计器(若实现 Transformer)做 inverseTransform,再从最后一步向前逐级还原。未实现逆变换的步骤会抛 BasaltUnsupportedOperationException。

参数
  • transformed (Matrix) – 已变换矩阵,列数须与最后一步输出一致

返回

还原到输入空间的矩阵

抛出
  • NullPointerException – transformed 为 null

  • IllegalStateException – 任一步尚未拟合

  • basalt.BasaltUnsupportedOperationException – 某步未实现 inverseTransform

predict(Matrix features) → double[]

变换后交由最终估计器预测

先依次 transform 各步,再由最终估计器预测。未挂估计器且最后一步实现 Estimator 时,把原始 features 交给该步的 predict;两者都没有时返回变换后矩阵的展平数组。

参数
  • features (Matrix) – 待预测特征矩阵

返回

长度等于行数的预测数组;无估计器时为展平的特征

抛出
  • NullPointerException – features 为 null

  • IllegalStateException – 任一步或最终估计器尚未拟合

  • IllegalArgumentException – 列数不匹配或含非有限值

steps() → List<Step>

步骤列表

返回

不可变的 Step 列表,顺序与构建顺序一致

estimator() → Estimator

最终估计器

返回

构建时指定的估计器;未挂估计器时为 null

estimatorName() → String

最终估计器在管道中的名称

返回

名称;未挂估计器时为 null;无名称重载默认取 estimator

namedSteps() → Map<String, Object>

步骤名到对象的映射

按插入顺序返回步骤名 → Transformer;挂了最终估计器时再追加其名称 → Estimator。

注意

名称重复时保留最后一次写入的对象

返回

不可修改的映射视图

kind() → ModelKind

模型族标识

返回

固定为 ModelKind.PIPELINE

write(ModelWriter writer)

写出步骤链与最终估计器

先写步骤数,再对每步写名称、类型码、负载长度与负载,负载由该步自己的 write 生成;随后写一个字节标记是否存在最终估计器,存在时再写名称、类型码与负载。

注意

每段负载写入独立缓冲区并加长度前缀,读取端据此切分

参数
  • writer (ModelWriter) – 目标二进制写入器

抛出
  • IllegalStateException – 最终估计器未实现 Persistable

read(ModelReader reader) → Pipelinestatic

按类型码重建步骤链与估计器

参数
  • reader (ModelReader) – 定位在管道负载起始处的读取器

返回

重建的管道,各步参数已恢复

抛出
  • ModelFormatException – 步骤数越界、字符串长度越界、负载不是 Transformer/Estimator 或类型码未知

final class PolynomialFeatures implements Transformer, Estimator

生成最高到 degree 的多项式与交互特征

fit 只记录输入特征数并按 degree、interactionOnly、includeBias 枚举列组合,不做任何数据统计,因此同参数下任意训练集得到相同的组合表。

每个输出列是一组输入列的乘积:interactionOnly 为 false 时组合内允许重复索引,得到 x_j^2 这类幂项;为 true 时索引严格递增,只保留不同特征的交互。includeBias 为 true 时额外输出一列常量 1,对应空组合。

transform 按组合表逐行求乘积;predict 返回展平结果,长度是 rows × 输出列数,而非每行一个值。

示例
Matrix x = Matrix.fromRows(new double[][]{{1.0, 2.0}, {3.0, 4.0}});

PolynomialFeatures poly = PolynomialFeatures.builder()
        .degree(2)
        .interactionOnly(false)
        .includeBias(true)
        .build()
        .fit(x);

Matrix expanded = poly.transform(x);
int columns = poly.outputFeatureCount();

注意

degree 默认 2,interactionOnly 默认 false,includeBias 默认 true

注意

输出列数只由输入特征数与三个参数决定,与样本量无关

注意

序列化只写四个字段,读回时按同样参数重新枚举组合表

参见:basalt.ml.Transformer, basalt.ml.StandardScaler, basalt.ml.Pipeline

方法

builder() → Builderstatic

创建构建器,degree=2、含 bias、保留幂项

返回

新的 Builder,字段取默认值

fit(Matrix features) → PolynomialFeatures

按特征数枚举列组合

参数
  • features (Matrix) – 训练特征矩阵,只使用其列数

返回

this

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – 特征含 NaN 或无穷值

fit(Matrix features, double[] ignoredTargets) → PolynomialFeatures

忽略目标值的拟合

参数
  • features (Matrix) – 训练特征矩阵,只使用其列数

  • ignoredTargets (double[]) – 被忽略,可为 null

返回

this

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – 特征含 NaN 或无穷值

transform(Matrix features) → Matrix

按组合表逐行求乘积

参数
  • features (Matrix) – 待变换矩阵,列数须等于拟合时的特征数

返回

rows × outputFeatureCount() 的新矩阵

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

predict(Matrix features) → double[]

返回变换结果的展平数组

参数
  • features (Matrix) – 待变换矩阵,列数须等于拟合时的特征数

返回

长度为 rows × 输出列数的数组

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

outputFeatureCount() → int

已枚举的输出列数

返回

输出列数,含 bias 列

抛出
  • IllegalStateException – 尚未 fit

kind() → ModelKind

模型族标识

返回

固定为 ModelKind.POLYNOMIAL_FEATURES

write(ModelWriter writer)

写出 degree、两个开关与输入特征数

组合表不落盘,read 时按同样参数重建。

参数
  • writer (ModelWriter) – 目标二进制写入器

抛出
  • IllegalStateException – 尚未 fit

read(ModelReader reader) → PolynomialFeaturesstatic

按四个字段重建组合表

参数
  • reader (ModelReader) – 定位在负载起始处的读取器

返回

可直接 transform 的实例

抛出
  • ModelFormatException – degree < 1 或输入特征数 ≤ 0

final class RFE implements Transformer, Estimator

按重要性递归剔除特征直到保留指定数量

每轮在当前保留的特征子集上通过工厂新建估计器并拟合,取其重要性——树模型的 featureImportances,或线性模型权重的绝对值——把重要性最低的 step 个特征标记为剔除;剩余数量不足 step 时只剔除到目标数量为止。

剔除轮次记录在 ranking 中:未被剔除的特征为 1,每经历一轮剔除加 1,因此数值越大表示越早被淘汰。循环结束后用保留特征重新拟合一个估计器作为最终模型;transform 只做列切片,predict 为切片后再预测。

重要性来源覆盖 DecisionTree、RandomForest、HistogramGradientBoosting 的 featureImportances,以及 Ridge、Lasso、LinearRegression、LogisticRegression、LinearSVM 的权重绝对值;其他估计器无法提供重要性,拟合时直接拒绝。

示例
Matrix x = Matrix.fromRows(new double[][]{
        {1.0, 0.5, 9.0}, {2.0, 1.5, 8.0},
        {3.0, 1.0, 7.0}, {4.0, 2.0, 6.0}});
double[] y = {1.0, 2.0, 3.0, 4.0};

RFE rfe = RFE.builder(() -> Ridge.builder().alpha(0.1).build())
        .nFeaturesToSelect(2)
        .step(1)
        .build()
        .fit(x, y);

Matrix reduced = rfe.transform(x);
boolean[] mask = rfe.support();
int[] ranking = rfe.ranking();
int[] indices = rfe.selectedIndices();

注意

nFeaturesToSelect 默认 2、step 默认 1,两者都必须在构建时为正

注意

每轮都新建估计器,工厂必须返回未拟合的新实例

注意

kind() 复用 ModelKind.SELECT_K_BEST,类中没有 read,写入负载格式与 SelectKBest 一致

注意

总拟合次数为剔除轮数加一,轮数约为 ceil((p − k)/step)

参见:basalt.ml.SelectKBest, basalt.ml.Ridge, basalt.ml.RandomForest, basalt.ml.Transformer

方法

builder(Supplier<Estimator> estimatorSupplier) → Builderstatic

指定估计器工厂并创建构建器

参数
  • estimatorSupplier (Supplier<Estimator>) – 每轮返回一个新的未拟合估计器

返回

新的 Builder,nFeaturesToSelect=2、step=1

抛出
  • NullPointerException – estimatorSupplier 为 null

fit(Matrix features, double[] targets) → RFE

递归剔除特征并用保留列重拟合

每轮对当前子集新建估计器、拟合、取重要性并按升序剔除 step 个特征;循环结束后在保留列上再拟合一个估计器作为最终模型。

注意

最后一轮剔除数量可能少于 step,以恰好保留目标数量为准

参数
  • features (Matrix) – 训练特征矩阵,行数为样本数

  • targets (double[]) – 训练目标数组,长度须等于行数

返回

this,已完成剔除与最终拟合

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – 目标数量与行数不符、含非有限值、nFeaturesToSelect 超出 [1, 特征数],或估计器既不提供 featureImportances 也没有长度匹配的 weights

transform(Matrix features) → Matrix

只保留入选列

参数
  • features (Matrix) – 待切片矩阵,列数须等于拟合时的特征数

返回

rows × nFeaturesToSelect 的新矩阵,列序与原始列序一致

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

predict(Matrix features) → double[]

切片后交由最终估计器预测

参数
  • features (Matrix) – 待预测矩阵,列数须等于拟合时的特征数

返回

长度等于行数的预测数组

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

support() → boolean[]

入选特征的布尔掩码

返回

长度为原始特征数的副本,true 表示保留

抛出
  • IllegalStateException – 尚未 fit

ranking() → int[]

特征淘汰次序

入选特征为 1,每被剔除一轮加 1,数值越大淘汰越早。

返回

长度为原始特征数的副本

抛出
  • IllegalStateException – 尚未 fit

selectedIndices() → int[]

入选列的原始下标,升序

返回

长度为 nFeaturesToSelect 的副本

抛出
  • IllegalStateException – 尚未 fit

estimator() → Estimator

最终重拟合的估计器

返回

已拟合的估计器;尚未 fit 时为 null

kind() → ModelKind

模型族标识

注意

与 SelectKBest 共用类型码,便于管道统一落盘

返回

固定为 ModelKind.SELECT_K_BEST

write(ModelWriter writer)

写出保留数量、伪分数与入选下标

伪分数取 1/ranking,用于在只识别分数的读取端表达排序;类本身没有 read 方法。

参数
  • writer (ModelWriter) – 目标二进制写入器

抛出
  • IllegalStateException – 尚未 fit

final class RandomForest implements Estimator, Persistable

自助聚合的直方图森林,节点级特征子采样

每棵树对行做有放回采样,随后在同一份全局 BinnedFeatures 上以直方图分裂生长。树之间相互独立,拟合通过 ForkJoinPool 并行,并行度由 threads 决定。

分类按各树叶标签投票,得到每类的得票比例后取最大者;回归取各树叶值的算术均值。行数乘树数不小于 2000 万时,预测与投票转交 Rust 内核,失败则回退 Java 路径。

OOB 分数只用对该行未被抽中的树计算:回归为 1 - SSE/SST,分类为多数投票的准确率。某行没有任何可用树或目标方差为零时返回 NaN。

示例
Matrix x = Matrix.fromRows(new double[][]{
        {0.0, 1.0}, {1.0, 1.0}, {1.0, 0.0}, {2.0, 0.0},
        {2.0, 1.0}, {3.0, 0.0}, {3.0, 1.0}, {4.0, 0.0}});
double[] y = {0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0};

RandomForest forest = RandomForest.builder()
        .trees(50)
        .maxDepth(6)
        .minSamplesLeaf(1)
        .maxFeatures(1)
        .bins(64)
        .threads(4)
        .seed(42L)
        .task(TreeTask.CLASSIFICATION)
        .oob(true)
        .build()
        .fit(x, y);

double[] label = forest.predict(x);
Matrix probability = forest.predictProbability(x);
double oob = forest.oobScore();

注意

OOB 打开时,treeCount*rows 超过 800 万会拒绝拟合

注意

maxFeatures 为 0 时按 max(1, sqrt(featureCount)) 解析

注意

readState 重建的森林关闭 OOB,oobScore() 会抛 IllegalStateException

参见:basalt.ml.DecisionTree, basalt.ml.PackedTrees, basalt.ml.TreeTask

方法

builder() → Builderstatic

创建构造器,参数全部取默认值

返回

新的 Builder 实例

fit(Matrix features, double[] targets) → RandomForest

分箱一次并并行训练全部树

全量矩阵只分箱一次,各树在共享分箱上以自助采样行号生长。第 i 棵树的随机种子为 seed + i*31,自助采样序列由 seed + i*1000003 驱动;打开 OOB 时,每棵树还会对全量矩阵推理一次以记录袋外预测。

注意

并行度由 threads 决定,树之间无共享可变状态

注意

分类标签按升序去重,classes() 返回该顺序

参数
  • features (Matrix) – 训练特征矩阵,行数为样本数

  • targets (double[]) – 目标数组,长度须等于行数;分类为类别标签,回归为连续值

返回

this,已完成拟合

抛出
  • IllegalArgumentException – 目标数量与行数不一致、含非有限值,或 OOB 评估超过 800 万次树-行预测

predict(Matrix features) → double[]

输出预测,分类为投票胜出的标签

回归对各树叶值取均值,可用原生内核一次算完整片森林;分类先取每类的平均得票比例,再按类别顺序取最大值,票数相同时取下标较小者。

参数
  • features (Matrix) – 特征矩阵,列数须等于拟合时的特征数

返回

长度为行数的预测数组

抛出
  • IllegalStateException – 尚未拟合

  • IllegalArgumentException – 列数不匹配或含非有限值

predictProbability(Matrix features) → Matrix

输出各类得票比例矩阵

每棵树对一行预测一个叶标签,映射到类别列后累加 1/treeCount,因此每行元素之和为 1。叶标签必须能在 classes() 中二分查到,否则抛 IllegalStateException。

参数
  • features (Matrix) – 特征矩阵,列数须等于拟合时的特征数

返回

rows × classes 的矩阵,列顺序与 classes() 一致

抛出
  • IllegalStateException – 任务不是分类,或尚未拟合

  • IllegalArgumentException – 列数不匹配或含非有限值

classes() → double[]

分类任务的类别标签,按升序排列

返回

类别标签副本;回归任务返回 null

task() → TreeTask

构造时指定的任务类型

返回

CLASSIFICATION 或 REGRESSION

oobScore() → double

袋外评估分数

回归为袋外预测的决定系数 1 - SSE/SST,分类为袋外多数投票的准确率。只用对该行未被抽中的树参与计算。

注意

启用 oob 但尚未拟合时返回 NaN,因为分数初值为 NaN

返回

OOB 分数;无可用袋外样本或 SST 为 0 时为 NaN

抛出
  • IllegalStateException – 构建时未启用 oob

featureImportances() → double[]

森林级特征重要性,总和为 1

先对各树已归一化的重要性求平均,再对平均值整体归一化。单叶树的重要性全为 0,因此对结果没有贡献。

返回

长度为特征数的数组,总和为 1

抛出
  • IllegalStateException – 尚未拟合

treeCount() → int

已拟合的树数

返回

树数;未拟合为 0

writeState(ModelWriter writer)

写出任务、类别与逐棵树的状态

写入任务序号、特征数、类别数(回归写 0)与类别标签、树数,随后逐棵调用 DecisionTree.writeState。超参数与 OOB 配置不落盘。

参数
  • writer (ModelWriter) – 目标二进制写入器

抛出
  • IllegalStateException – 尚未拟合

readState(ModelReader reader) → RandomForeststatic

从二进制流重建森林

注意

重建后 OOB 关闭,oobScore() 会抛 IllegalStateException

注意

重建后的特征重要性全为 0

参数
  • reader (ModelReader) – 已定位到本对象载荷起点的读取器

返回

新的 RandomForest 实例,已完成树拼接

抛出
  • ModelFormatException – 任务序号越界、分类森林缺少类别标签,或树数不在 [1, 100000]

kind() → ModelKind

持久化类型标识

返回

ModelKind.RANDOM_FOREST

write(ModelWriter writer)

按 Persistable 契约写模型

注意

实现为直接调用 writeState

参数
  • writer (ModelWriter) – 目标二进制写入器

final class RandomizedSearchCV implements Estimator

按参数分布随机采样并交叉验证选优

fit 先按 cv 折数与 stratified 开关切分数据(打乱开启,种子取 seed),再用同一个 Random(seed) 为每次迭代从各参数分布各采一个值。每折都通过工厂新建估计器、拟合并预测,按 scoring 计算该折分数。

每次迭代记录参数、折分数均值与总体标准差(除以折数),存为 CandidateResult;均值严格更大才替换当前最优,因此并列时保留先出现的参数组。全部迭代结束后用最优参数在全量数据上重新拟合,作为最终模型。

参数分布由构建器的 paramChoices、paramUniform、paramLogUniform、paramIntRange 登记,采样在 fit 内按登记顺序进行,顺序固定使同一 seed 可复现。

示例
Matrix x = Matrix.fromRows(new double[][]{
        {0.0, 1.0}, {1.0, 1.0}, {1.0, 0.0}, {2.0, 0.0},
        {2.0, 1.0}, {3.0, 0.0}, {3.0, 1.0}, {4.0, 0.0}});
double[] y = {0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0};

RandomizedSearchCV search = RandomizedSearchCV
        .builder(params -> Ridge.builder()
                .alpha((Double) params.get("alpha")).build())
        .paramLogUniform("alpha", 1e-3, 10.0)
        .nIter(20)
        .cv(4)
        .scoring(basalt.ml.Estimators.Metric.R2)
        .seed(7L)
        .build()
        .fit(x, y);

double[] predictions = search.predict(x);
Map<String, Object> best = search.bestParams();
double score = search.bestScore();

注意

默认 nIter=10、cv=5、scoring=ACCURACY、stratified=false、seed=42

注意

RMSE 以负值参与比较,使所有指标都按越大越好处理

注意

每次迭代每折都新建估计器,总拟合次数为 nIter × cv 再加一次全量拟合

注意

cvResults 只保存参数与分数,不保存各折模型

参见:basalt.ml.GridSearchCV, basalt.ml.StratifiedKFold, basalt.ml.DataSplit

方法

builder(Function<Map<String, Object>, Estimator> estimatorFactory) → Builderstatic

指定估计器工厂并创建构建器

参数
  • estimatorFactory (Function<Map<String, Object>, Estimator>) – 把一组参数映射构造成未拟合估计器

返回

新的 Builder,字段取默认值

抛出
  • NullPointerException – estimatorFactory 为 null

fit(Matrix features, double[] targets) → RandomizedSearchCV

随机采样、逐折评估后全量重拟合

每次迭代先采样一组参数,再在全部折上分别新建估计器、拟合、预测并评分;记录均值与标准差后与当前最优比较,最后用最优参数在全量数据上重拟合。

注意

同一 seed 下折划分与采样序列都可复现

参数
  • features (Matrix) – 训练特征矩阵,行数为样本数

  • targets (double[]) – 训练目标数组,长度须等于行数

返回

this,bestEstimator 已在全量数据上拟合

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – 目标数量与行数不符、含非有限值,或折数超出 [2, 行数]

predict(Matrix features) → double[]

用最优参数的模型预测

参数
  • features (Matrix) – 待预测特征矩阵

返回

长度等于行数的预测数组

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

bestEstimator() → Estimator

全量数据上重拟合的最优模型

返回

已拟合的估计器

抛出
  • IllegalStateException – 尚未 fit

bestParams() → Map<String, Object>

最优参数组

返回

不可修改的参数映射,键为登记的参数名

抛出
  • IllegalStateException – 尚未 fit

bestScore() → double

最优交叉验证均分

返回

折分数均值;scoring 为 RMSE 时取负值

抛出
  • IllegalStateException – 尚未 fit

cvResults() → List<GridSearchCV.CandidateResult>

逐次迭代的评估记录

注意

尚未 fit 时返回空列表,不抛异常

返回

按迭代顺序排列的不可修改列表,元素为 GridSearchCV.CandidateResult

final class Ridge implements Estimator, Persistable

Cholesky 求解的 L2 正则最小二乘。

fitIntercept 为 true 时先计算特征均值与目标均值,在中心化后的数据上累加 Gram 矩阵与右端项,对 Gram 对角线加 alpha 后用 Cholesky 分解解正规方程,最后用均值反推截距;为 false 时不中心化,直接对原始矩阵求解。

alpha 加在按行求和的 Gram 尺度上(未除以样本数),与按均方误差定义的 alpha 相差 n 倍。分解时对角元取 max(sum, 1e-12) 作为抖动,避免半正定退化导致 NaN。

示例
Matrix x = Matrix.fromRows(new double[][]{{0, 0}, {0, 1}, {1, 0}, {1, 1}});
double[] y = {0.0, 1.0, 1.0, 2.0};
Ridge ridge = Ridge.builder()
        .alpha(0.5)
        .fitIntercept(true)
        .build()
        .fit(x, y);
double[] coefficients = ridge.weights();
double bias = ridge.intercept();
double[] predictions = ridge.predict(x);

注意

样本数不少于 512、特征数不少于 4 且原生内核可用时走 Rust 路径,调用失败则回退到纯 Java 实现

注意

原生路径的线程数取可用处理器数

注意

alpha 必须严格为正,0 会在 build() 时被拒绝

注意

训练与预测都是单次批量运算,不迭代

参见:basalt.ml.Lasso, basalt.ml.LinearRegression, basalt.ml.Ridge.Builder

方法

builder() → Builderstatic

创建构建器,默认 alpha=1.0、拟合截距。

返回

新的 Builder,字段取默认值

fit(Matrix features, double[] targets) → Ridge

组装正规方程并用 Cholesky 求解。

Gram 矩阵只累加上三角再对称填充,随后逐行加 alpha;Cholesky 得到下三角因子后先前代再回代,得到系数向量。

注意

纯 Java 路径的代价为 O(n·d²) 时间与 O(d²) 额外内存

注意

原生路径失败时静默回退,不抛异常

参数
  • features (Matrix) – 训练特征矩阵,n 行 d 列

  • targets (double[]) – 训练目标数组,长度等于 n

返回

this

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – 行数与目标长度不符,或数据含 NaN/无穷

predict(Matrix features) → double[]

计算截距与系数的点积。

注意

逐行调用 VectorMath.dot,不做批量矩阵乘

参数
  • features (Matrix) – 待预测特征矩阵,列数须等于训练特征数

返回

长度等于行数的连续预测值

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

weights() → double[]

返回回归系数副本。

返回

长度为特征数的系数副本

抛出
  • NullPointerException – 尚未 fit,内部数组为 null

intercept() → double

返回截距项。

注意

截距不参与正则化,由 targetMean 减去各特征均值与系数的乘积得到

返回

标量截距;未 fit 或 fitIntercept 为 false 时为 0.0

kind() → ModelKind

模型族标识

返回

固定为 ModelKind.RIDGE

write(ModelWriter writer)

写出超参数、截距与系数

依次写 alpha、fitIntercept 标志字节、特征数、截距与系数数组,不写训练数据。

注意

字段顺序须与 read 严格对应,否则校验和通过但字段整体错位

参数
  • writer (ModelWriter) – 目标二进制写入器

抛出
  • IllegalStateException – 尚未 fit

read(ModelReader reader) → Ridgestatic

按写入顺序重建线性模型

参数
  • reader (ModelReader) – 定位在负载起始处的读取器

返回

可直接 predict 的 Ridge 实例,alpha 与 fitIntercept 一并恢复

抛出
  • ModelFormatException – 特征数 ≤ 0 或负载截断

final class SVC implements Estimator, Persistable

SMO 求解的核支持向量分类器,支持 OvR 多分类与 Platt 概率校准。

fit 对整个训练集计算一次核 Gram 矩阵并整体留作支持向量集合,随后用 SMO 求解对偶问题:外层遍历样本,内层挑选使 |E_i − E_j| 最大的样本做联合更新,并以 15% 概率改取随机合作样本以跳出平台;连续 5 轮无更新或达到 maxIterations 时停止。

核由 Kernel 描述:LINEAR 为内积,RBF 为 exp(−gamma·‖x−y‖²),POLY 为 (gamma·x·y + coef0)^degree,SIGMOID 为 tanh(gamma·x·y + coef0)。c 是对偶变量上界,越小正则越强;RBF 与 POLY 的 gamma 控制单点影响半径,越大决策边界越弯曲。

开启 probability(true) 后,fit 末尾对每个二分类子问题做 Platt 校准:标签先平滑(正类 (N₊+1)/(N₊+2),负类 1/(N₋+2)),再用带阻尼的牛顿法最小化负对数似然,求出 P(y=+1|f) = 1/(1+exp(A·f+B)) 的 A、B。多分类对每个 OvR 模型各自校准,再按概率和归一化。

注意

默认 kernel 为 rbf(1.0)、c=1.0、tolerance=1e-4、maxIterations=600、seed=42、probability=false

注意

未开启 probability 时调用 predictProbability 抛 IllegalStateException;校准参数 A、B 随模型一起序列化

注意

Gram 矩阵为 n×n,内存随样本数平方增长;预测对每个样本遍历全部训练行

注意

所有训练行都保留为支持向量,不做 alpha 为零的剪枝,模型体积与训练集同阶

注意

校准在训练集决策值上拟合,样本很少或数据近似可分时 |A| 会很大,概率贴近 0/1

方法

builder() → Builderstatic

创建构建器,默认 RBF 核 gamma=1.0

返回

新的 Builder,字段取默认值

fit(Matrix features, double[] targets) → SVC

计算 Gram 矩阵并用 SMO 求解对偶问题

类别标签按升序去重;二分类只训练一个模型,多分类为每个类别训练一个 One-vs-Rest 模型,系数按 alpha·y 存储以便预测时直接加权求和。

注意

Gram 矩阵一次算完并复用,每轮迭代的更新代价为 O(n)

参数
  • features (Matrix) – 训练特征矩阵,行数为样本数

  • targets (double[]) – 类别标签数组,长度须等于行数

返回

this,已完成训练

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – 目标数量与行数不符、含非有限值,或不同类别数少于 2

decisionFunction(Matrix features) → double[]

输出未校准的判别值

二分类为 Σ alpha_i·y_i·K(x_i, x) + b,符号决定类别;多分类只返回第 0 个 One-vs-Rest 模型的判别值。

注意

数值是间隔而非概率,不能直接解释为置信度

参数
  • features (Matrix) – 待评估矩阵,列数须等于训练特征数

返回

长度等于行数的判别值,0 为二分类的决策边界

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

predictProbability(Matrix features) → Matrix

返回校准后的类别概率,形状 [n, classes.length]

参数
  • features (Matrix) – 与训练集列数一致的特征矩阵

返回

每行之和为 1;二分类两列依次为 P(classes[0])、P(classes[1])

抛出
  • IllegalStateException – 构建时未开启 probability(true)

predict(Matrix features) → double[]

输出预测类别标签

二分类按判别值是否不小于 0 取 classes[1] 或 classes[0];多分类对每个 One-vs-Rest 模型求判别值并取最大者,并列时取下标较小者。

参数
  • features (Matrix) – 待预测矩阵,列数须等于训练特征数

返回

长度等于行数的类别标签

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

kernel() → Kernel

构建时指定的核函数

返回

Kernel 实例,含类型、gamma、degree 与 coef0

probabilityEnabled() → boolean

是否启用了 Platt 概率校准

返回

构建时传入的 probability 标志

classes() → double[]

训练期的类别标签,按升序排列

返回

类别标签副本;尚未 fit 时为 null

kind() → ModelKind

模型族标识

返回

固定为 ModelKind.SVC

write(ModelWriter writer)

写出核参数、超参数与全部对偶系数

依次写 Kernel、c、tolerance、maxIterations、seed、特征数、类别数与类别、支持向量行数与数据、模型数、逐个模型的 alpha 与截距。

注意

支持向量集合即全部训练行,负载大小与训练集同阶

参数
  • writer (ModelWriter) – 目标二进制写入器

抛出
  • IllegalStateException – 尚未 fit

read(ModelReader reader) → SVCstatic

按写入顺序重建模型

参数
  • reader (ModelReader) – 定位在负载起始处的读取器

返回

可直接 predict 的实例,超参数一并恢复

抛出
  • ModelFormatException – 特征数 ≤ 0、类别数 < 2 或负载截断

final class SelectKBest implements Transformer, Estimator

按单变量统计量保留得分最高的 k 个特征

fit 逐列计算评分,按分数降序排列(同分取原始下标较小者),保留前 k 列,再把入选下标升序排列。transform 只做列切片,predict 返回展平结果,两者都不重新计算分数。

三种口径各有适用范围:F_CLASSIF 是单因素方差分析的 F 值 MSB/MSW,自由度为 max(1, C−1) 与 max(1, n−C),用于分类目标;F_REGRESSION 先算特征与目标的 Pearson 相关系数 r,再转成 F = r²/(1−r²)·(n−2),用于回归目标;CHI2 把特征值视为非负计数,按类别累加观测与期望频数之差的卡方和,用于非负特征配分类目标。

组内均方为 0(特征在类内完全不变)时 F_CLASSIF 记 0 分以避免除零;相关系数分母退化时 F_REGRESSION 同样记 0 分。

示例
Matrix x = Matrix.fromRows(new double[][]{
        {1.0, 0.1, 5.0}, {1.2, 0.2, 4.9},
        {3.0, 0.1, 5.1}, {3.1, 0.3, 5.0}});
double[] y = {0.0, 0.0, 1.0, 1.0};

SelectKBest selector = SelectKBest.builder()
        .k(2)
        .scoreFunc(SelectKBest.ScoreFunc.F_CLASSIF)
        .build()
        .fit(x, y);

Matrix selected = selector.transform(x);
double[] scores = selector.scores();
boolean[] support = selector.getSupport();

注意

k 默认 5,scoreFunc 默认 F_CLASSIF

注意

CHI2 遇到负特征值直接抛 IllegalArgumentException

注意

各列评分相互独立,不考虑特征之间的相关性

注意

写入时保存 k、口径、特征数、全部分数与入选下标,读回无需重算

参见:basalt.ml.RFE, basalt.ml.Pipeline, basalt.ml.Transformer

方法

builder() → Builderstatic

创建构建器,k=5、F_CLASSIF 口径

返回

新的 Builder,字段取默认值

fit(Matrix features, double[] targets) → SelectKBest

计算逐列评分并选出前 k 列

评分按口径分派到方差分析、相关系数转 F 或卡方三种实现;排序后取前 k 个下标并升序整理。

注意

同分时保留原始下标较小的列

参数
  • features (Matrix) – 训练特征矩阵,行数为样本数

  • targets (double[]) – 目标数组,长度须等于行数;分类口径下按类别标签处理

返回

this,已确定入选列

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – 目标数量与行数不符、含非有限值、k 超出 [1, 特征数],或 CHI2 口径下特征含负值

transform(Matrix features) → Matrix

只保留入选列

参数
  • features (Matrix) – 待切片矩阵,列数须等于拟合时的特征数

返回

rows × k 的新矩阵,列序按原始下标升序

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

predict(Matrix features) → double[]

返回切片结果的展平数组

参数
  • features (Matrix) – 待切片矩阵,列数须等于拟合时的特征数

返回

长度为 rows × k 的数组

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

scores() → double[]

每列的评分

返回

长度为原始特征数的副本,顺序与原始列一致

抛出
  • IllegalStateException – 尚未 fit

selectedIndices() → int[]

入选列的原始下标,升序

返回

长度为 k 的副本

抛出
  • IllegalStateException – 尚未 fit

getSupport() → boolean[]

入选特征的布尔掩码

返回

长度为原始特征数的数组,true 表示保留

抛出
  • IllegalStateException – 尚未 fit

kind() → ModelKind

模型族标识

返回

固定为 ModelKind.SELECT_K_BEST

write(ModelWriter writer)

写出 k、口径、特征数、分数与入选下标

参数
  • writer (ModelWriter) – 目标二进制写入器

抛出
  • IllegalStateException – 尚未 fit

read(ModelReader reader) → SelectKBeststatic

按写入顺序重建选择器

参数
  • reader (ModelReader) – 定位在负载起始处的读取器

返回

可直接 transform 的实例,评分与入选列已恢复

抛出
  • ModelFormatException – k ≤ 0、特征数小于 k 或口径序号越界

final class ShapExplainer

计算可加的 SHAP 归因值,满足 Σφ = f(x) − E[f]

构造时用背景数据集估计基准值:对背景矩阵逐行预测后取均值作为 baseValue,同时记录每列均值供线性路径使用。背景矩阵被复制保存,之后外部修改不影响解释器。

explain 对线性模型(LinearRegression、Ridge、Lasso)走闭式 LinearSHAP:φ_j = w_j·(x_j − E[X_j]),代价 O(p)。其他模型在特征数不超过 8 时枚举全部 2^p 个联盟并用 Shapley 权重精确求值;超过 8 时改用随机排列的蒙特卡洛采样,采样次数为 maxCoalitions。

三条路径都满足局部可加性:基准值加上同一行全部归因值之和等于该行预测值。蒙特卡洛路径在每条排列的最后一个特征上直接取真实预测,因此总和不因采样而偏移。

归因对象随模型类型切换:LogisticRegression 取 predictProbability,HistogramGradientBoosting 取 predictRaw,分类 RandomForest 取第 1 列概率,其余模型直接取 predict,保证归因值解释的是实际输出。

示例
Matrix x = Matrix.fromRows(new double[][]{
        {0.0, 1.0}, {1.0, 1.5}, {2.0, 0.5}, {3.0, 2.0}});
double[] y = {1.0, 2.0, 2.5, 3.5};

Ridge model = Ridge.builder().alpha(0.1).build().fit(x, y);
ShapExplainer explainer = new ShapExplainer(model, x, 64, 42L);

ShapExplainer.Explanation explanation = explainer.explain(x);
double base = explanation.baseValue();
Matrix phi = explanation.shapValues();
double[] predictions = explanation.predictions();
double[] importance = explanation.meanAbsShap();

注意

maxCoalitions 默认 64、seed 默认 42,采样次数必须不小于 4

注意

特征数 ≤ 8 时精确枚举,代价为 2^p × 背景行数 次预测,p 增大时增长极快

注意

背景矩阵列数必须与待解释矩阵一致,否则 explain 抛 IllegalArgumentException

注意

基准值是背景集预测均值,不是训练集目标均值

参见:basalt.ml.Ridge, basalt.ml.RandomForest, basalt.ml.HistogramGradientBoosting

构造器

ShapExplainer(Estimator model, Matrix background)

以默认采样参数构造解释器

等价于 maxCoalitions=64、seed=42 的重载,构造时即对背景集推理一次以得到基准值。

参数
  • model (Estimator) – 待解释的已拟合估计器

  • background (Matrix) – 背景数据集,用于估计基准值与各列均值

抛出
  • NullPointerException – model 或 background 为 null

  • IllegalArgumentException – 背景矩阵含 NaN 或无穷值

ShapExplainer(Estimator model, Matrix background, int maxCoalitions, long seed)

指定采样次数与随机种子构造解释器

背景矩阵被复制保存,列均值与基准值在构造阶段一次算好,后续 explain 复用。

注意

背景集预测在构造时执行一次,成本为背景行数次模型调用

参数
  • model (Estimator) – 待解释的已拟合估计器

  • background (Matrix) – 背景数据集,列数须与待解释数据一致

  • maxCoalitions (int) – 蒙特卡洛路径的排列采样次数,必须不小于 4

  • seed (long) – 排列采样的随机种子

抛出
  • NullPointerException – model 或 background 为 null

  • IllegalArgumentException – 背景矩阵含 NaN 或无穷值,或 maxCoalitions < 4

方法

baseValue() → double

背景集预测均值

返回

基准值 E[f],即背景矩阵逐行预测的算术均值

explain(Matrix instances) → Explanation

逐行计算归因值

返回记录含基准值、rows × p 的归因矩阵、逐行预测值与每列的平均绝对归因值。线性模型走闭式公式,特征数 ≤ 8 走联盟枚举,否则走蒙特卡洛采样。

注意

同一行归因值之和等于该行预测值减基准值

参数
  • instances (Matrix) – 待解释矩阵,列数须等于背景矩阵列数

返回

Explanation 记录,含 baseValue、shapValues、predictions 与 meanAbsShap

抛出
  • NullPointerException – instances 为 null

  • IllegalArgumentException – 列数与背景矩阵不一致或含非有限值

final class SimpleImputer implements Transformer, Estimator

用列统计量填补 NaN 缺失值

fit 逐列收集非 NaN 值并按 strategy 求填充值:MEAN 为算术均值,MEDIAN 为排序后取中位(偶数个取中间两值均值),MOST_FREQUENT 取出现次数最多的值(并列时取数值较小者),CONSTANT 直接使用 fillValue。统计量按列数固定,与后续样本无关。

transform 只替换 NaN,其他值原样保留,不会重新估计统计量;因此训练期与推理期对同一缺失位置使用同一常量。缺失的唯一标记是 NaN,无穷值被视为非法数据而非缺失。

非 CONSTANT 策略下某列全为 NaN 时没有可估计的统计量,fit 直接拒绝;CONSTANT 策略不受此限制,因为填充值由参数给出。

示例
Matrix x = Matrix.fromRows(new double[][]{
        {1.0, Double.NaN}, {2.0, 3.0},
        {Double.NaN, 4.0}, {4.0, 5.0}});

SimpleImputer imputer = SimpleImputer.builder()
        .strategy(SimpleImputer.Strategy.MEDIAN)
        .build()
        .fit(x);

Matrix filled = imputer.transform(x);
double[] statistics = imputer.statistics();

注意

strategy 默认 MEAN、fillValue 默认 0.0,fillValue 必须有限

注意

transform 要求列数与 fit 时一致,不会自动补齐或截断

注意

统计量随模型落盘,读回后可直接 transform,无需原始训练数据

注意

无穷值在 fit 与 transform 中都会抛 IllegalArgumentException

参见:basalt.ml.StandardScaler, basalt.ml.Pipeline, basalt.ml.Transformer

方法

builder() → Builderstatic

创建构建器,MEAN 策略、填充值 0.0

返回

新的 Builder,字段取默认值

fit(Matrix features) → SimpleImputer

估计每列填充值,忽略目标值

注意

该重载内部以 targets=null 调用双参版本

参数
  • features (Matrix) – 训练特征矩阵,NaN 视为缺失

返回

this

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – 含无穷值,或非 CONSTANT 策略下某列全为 NaN

fit(Matrix features, double[] ignoredTargets) → SimpleImputer

估计每列填充值

逐列扫描非 NaN 值并按键 strategy 求统计量;CONSTANT 策略直接写入 fillValue。

注意

MOST_FREQUENT 并列时取数值较小者,因为按升序遍历频次表

参数
  • features (Matrix) – 训练特征矩阵,NaN 视为缺失

  • ignoredTargets (double[]) – 被忽略,可为 null

返回

this

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – 含无穷值,或非 CONSTANT 策略下某列全为 NaN

transform(Matrix features) → Matrix

用列统计量替换 NaN

参数
  • features (Matrix) – 待填补矩阵,列数须等于拟合时的列数

返回

同形状的新矩阵,NaN 位置换成对应列统计量

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含无穷值

predict(Matrix features) → double[]

返回填补结果的展平数组

参数
  • features (Matrix) – 待填补矩阵,列数须等于拟合时的列数

返回

长度为 rows × 列数的数组

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含无穷值

statistics() → double[]

每列的填充值

返回

长度为列数的副本,顺序与列一致

抛出
  • IllegalStateException – 尚未 fit

strategy() → Strategy

构建时指定的填补策略

返回

MEAN、MEDIAN、MOST_FREQUENT 或 CONSTANT

kind() → ModelKind

模型族标识

返回

固定为 ModelKind.SIMPLE_IMPUTER

write(ModelWriter writer)

写出策略、填充值、列数与统计量

参数
  • writer (ModelWriter) – 目标二进制写入器

抛出
  • IllegalStateException – 尚未 fit

read(ModelReader reader) → SimpleImputerstatic

按写入顺序重建填补器

参数
  • reader (ModelReader) – 定位在负载起始处的读取器

返回

可直接 transform 的实例

抛出
  • ModelFormatException – 策略序号越界或列数 ≤ 0

final class StandardScaler implements Transformer, Estimator

按列去均值并缩放到单位方差

fit 逐列计算均值与总体方差(除以样本数,ddof=0),scale 取标准差;withStd 为 false 或标准差不超过 1e-12 时 scale 固定为 1.0,避免常量列除零。samplesSeen 记录参与统计的行数。

transform 按 z = (x − mean)/scale 逐元素计算,withMean 与 withStd 分别控制是否减均值、是否除标准差;inverseTransform 先乘 scale 再加 mean,两者互为逆运算。

拟合参数只在 fit 时估计,transform 与 inverseTransform 都不更新统计量;对训练时未出现的取值直接做线性映射,不裁剪也不截断,因此超出训练范围的值会产生绝对值更大的 z。

示例
Matrix x = Matrix.fromRows(new double[][]{
        {1.0, 10.0}, {2.0, 20.0}, {3.0, 30.0}, {4.0, 40.0}});

StandardScaler scaler = StandardScaler.builder()
        .withMean(true)
        .withStd(true)
        .build()
        .fit(x);

Matrix z = scaler.transform(x);
Matrix restored = scaler.inverseTransform(z);
double[] mean = scaler.mean();
double[] scale = scaler.scale();

注意

withMean 与 withStd 默认都为 true

注意

方差为总体方差,与样本方差相差 n/(n−1) 的系数

注意

常量列的 scale 为 1.0,该列变换后整体平移为零

注意

均值、缩放因子与方差随模型落盘,读回即可复现同一映射

参见:basalt.ml.MinMaxScaler, basalt.ml.SimpleImputer, basalt.ml.Pipeline

方法

builder() → Builderstatic

创建构建器,减均值且除标准差

返回

新的 Builder,withMean 与 withStd 均为 true

fit(Matrix features) → StandardScaler

估计每列均值与标准差

参数
  • features (Matrix) – 训练特征矩阵,行数为样本数

返回

this

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – 特征含 NaN 或无穷值

fit(Matrix features, double[] ignoredTargets) → StandardScaler

估计每列均值与标准差,忽略目标值

先累加求均值,再在中心化基础上累加平方和得到总体方差,最后取平方根作为 scale。

注意

两次遍历全矩阵,时间 O(n·d)、额外空间 O(d)

参数
  • features (Matrix) – 训练特征矩阵,行数为样本数

  • ignoredTargets (double[]) – 被忽略,可为 null

返回

this

抛出
  • NullPointerException – features 为 null

  • IllegalArgumentException – 特征含 NaN 或无穷值

transform(Matrix features) → Matrix

按列标准化

参数
  • features (Matrix) – 待变换矩阵,列数须等于拟合时的列数

返回

同形状的新矩阵

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

inverseTransform(Matrix transformed) → Matrix

还原到原始尺度

参数
  • transformed (Matrix) – 已标准化矩阵,列数须等于拟合时的列数

返回

同形状的新矩阵,与 transform 互为逆运算

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

predict(Matrix features) → double[]

返回标准化结果的展平数组

参数
  • features (Matrix) – 待变换矩阵,列数须等于拟合时的列数

返回

长度为 rows × 列数的数组

抛出
  • IllegalStateException – 尚未 fit

  • IllegalArgumentException – 列数不匹配或含非有限值

mean() → double[]

每列均值

返回

长度为列数的副本

抛出
  • IllegalStateException – 尚未 fit

scale() → double[]

每列缩放因子

返回

长度为列数的副本;未启用 withStd 或标准差过小时为 1.0

抛出
  • IllegalStateException – 尚未 fit

variance() → double[]

每列总体方差

返回

长度为列数的副本,除以样本数而非样本数减一

抛出
  • IllegalStateException – 尚未 fit

samplesSeen() → int

参与统计的样本数

返回

fit 时的行数;尚未 fit 时为 0

withMean() → boolean

是否减去均值

返回

构建时指定的开关

withStd() → boolean

是否除以标准差

返回

构建时指定的开关

kind() → ModelKind

模型族标识

返回

固定为 ModelKind.STANDARD_SCALER

write(ModelWriter writer)

写出开关、列数、样本数与三个数组

依次写 withMean、withStd 两个标志字节,列数、样本数,随后写均值、缩放因子与方差。

参数
  • writer (ModelWriter) – 目标二进制写入器

抛出
  • IllegalStateException – 尚未 fit

read(ModelReader reader) → StandardScalerstatic

按写入顺序重建缩放器

参数
  • reader (ModelReader) – 定位在负载起始处的读取器

返回

可直接 transform 的实例,三个数组均已恢复

抛出
  • ModelFormatException – 列数或样本数 ≤ 0

final class StratifiedKFold

保持类别比例的分层 K 折划分器

split 按目标值把行号分组,组内可选打乱(种子取 seed),再用跨类别连续累加的轮转计数器把行号依次放入各折,使每折的类别比例接近整体;某一类的样本数少于折数时无法分层,直接拒绝。

返回的每个 Fold 含训练与测试两部分的特征矩阵与目标数组,训练部分由其余折按折序拼接,行序与原始数据不同。划分只读取目标值,不拟合任何模型。

示例
Matrix x = Matrix.fromRows(new double[][]{
        {0.0, 0.0}, {0.2, 0.1}, {1.0, 1.0},
        {1.1, 0.9}, {2.0, 2.0}, {2.2, 1.8}});
double[] y = {0.0, 0.0, 1.0, 1.0, 2.0, 2.0};

StratifiedKFold cv = new StratifiedKFold(3, true, 42L);
List<DataSplit.Fold> folds = cv.split(x, y);
DataSplit.Fold first = folds.get(0);
Matrix trainX = first.trainFeatures();
double[] testY = first.testTargets();

注意

folds 必须不小于 2,split 时还要求不超过样本数

注意

单参构造等价于 shuffle=true、seed=42

注意

轮转计数器跨类别累加,分层是近似的:各类样本数不能整除折数时每折数量会差 1

注意

种子固定时同一实例多次 split 结果相同

参见:basalt.ml.DataSplit, basalt.ml.GridSearchCV, basalt.ml.RandomizedSearchCV

构造器

StratifiedKFold(int folds)

使用默认打乱与种子构造划分器

注意

等价于 shuffle=true、seed=42

参数
  • folds (int) – 折数,必须不小于 2

抛出
  • IllegalArgumentException – folds < 2

StratifiedKFold(int folds, boolean shuffle, long seed)

指定折数、打乱开关与种子

参数
  • folds (int) – 折数,必须不小于 2

  • shuffle (boolean) – 是否在分折前打乱每个类别内部的行序

  • seed (long) – 打乱使用的随机种子

抛出
  • IllegalArgumentException – folds < 2

方法

folds() → int

折数

返回

构造时指定的折数

shuffle() → boolean

是否在划分前打乱

返回

构造时指定的开关

split(Matrix features, double[] targets) → List<DataSplit.Fold>

执行分层划分

按类别分组后轮转分配到各折,再以其余折拼接训练集。

参数
  • features (Matrix) – 特征矩阵,行数为样本数

  • targets (double[]) – 类别标签数组,长度须等于行数

返回

长度为 folds 的 Fold 列表,顺序与折号一致

抛出
  • NullPointerException – features 或 targets 为 null

  • IllegalArgumentException – 目标数量与行数不符、含非有限值、folds 超出 [2, 行数],或某类样本数少于折数

interface Transformer extends Persistable

有状态特征预处理与特征工程步骤的统一契约

实现类在 fit 阶段从数据中学出统计量(均值、尺度、类别词表、缺失填充常数、分桶边界、被选中的特征掩码),在 transform 阶段用这些统计量改写特征矩阵。继承 Persistable 使统计量可以单独写入 .bsl 容器,也可以随 Pipeline 一起序列化,从而保证训练与线上推理的行为逐位一致。

fit(Matrix) 等价于 fit(features, null);fitTransform 先把特征交给 fit,再对同一批数据执行 transform,省去一次显式调用。inverseTransform 的默认实现直接抛 BasaltUnsupportedOperationException,只有映射可逆的变换(MinMaxScaler、LabelEncoder、特征选择等)才覆盖它。

示例
MinMaxScaler scaler = MinMaxScaler.builder()
        .featureRange(0.0, 1.0)
        .build();

Matrix scaled = scaler.fitTransform(features);
Matrix restored = scaler.inverseTransform(scaled);

注意

fit 的实现必须返回自身或等价实例,默认的 fit(Matrix) 正是把返回值继续传给 fit(Matrix, double[])

注意

transform 不修改入参,返回新的 Matrix;列数由 fit 阶段记录的特征决定

注意

无监督变换忽略 targets,只有目标编码一类步骤会真正读取它

参见:basalt.ml.Pipeline, basalt.core.Persistable, basalt.core.Matrix

enum TreeTask

单棵决策树的监督目标:分类或回归

CLASSIFICATION 用类别计数与 GINI 或 ENTROPY 评估分裂,叶值为多数类标签;REGRESSION 用和与平方和计算方差下降,叶值为均值。任务同时决定 fit 的编码方式、predict 的输出语义以及 Builder 对准则的校验。

示例
DecisionTree regressor = DecisionTree.builder()
        .task(TreeTask.REGRESSION)
        .maxDepth(6)
        .build();

TreeTask task = regressor.task();

注意

task 与 criterion 必须匹配,否则 DecisionTree.Builder.build() 抛 IllegalArgumentException

注意

RandomForest 与 DecisionTree 都把任务作为构造期常量,拟合后不可更改

参见:basalt.ml.DecisionTree, basalt.ml.ImpurityCriterion, basalt.ml.RandomForest

枚举成员

CLASSIFICATION()

分类树,叶子输出类别或类分布

REGRESSION()

回归树,叶子输出均值

static final class AgglomerativeClustering.Builder

AgglomerativeClustering 的构建器。

只有两个参数:目标簇数 clusters 与连接准则 linkage,默认 2 与 WARD。clusters 在 setter 内立即校验为正,linkage 只做非空检查,build 直接返回未拟合实例,不再重复校验。

两个参数都可省略,AgglomerativeClustering.builder() 返回的构建器已带默认值,因此最简用法是 build 后直接 fit。

示例
AgglomerativeClustering model = AgglomerativeClustering.builder()
        .clusters(3)
        .linkage(AgglomerativeClustering.Linkage.AVERAGE)
        .build();

model.fit(features);
int[] labels = model.labels();

注意

必填项:无;clusters 与 linkage 都有默认值

注意

fit 阶段会另外校验 clusters 不超过样本数,该约束不在 build 时检查

注意

链接准则决定合并代价的计算方式,选择前建议先做特征标准化

参见:basalt.ml.AgglomerativeClustering, basalt.ml.AgglomerativeClustering.Linkage

方法

clusters(int clusters) → Builder

设置目标簇数,默认 2。

注意

此处即完成校验,非法值不会传播到 build

参数
  • clusters (int) – 期望保留的簇数,须为正;默认 2

返回

this,便于链式调用

抛出
  • IllegalArgumentException – clusters 小于等于 0

linkage(Linkage linkage) → Builder

设置簇间连接准则,默认 WARD。

参数
  • linkage (Linkage) – Linkage 常量之一:WARD、COMPLETE、AVERAGE 或 SINGLE,非 null

返回

this,便于链式调用

抛出
  • NullPointerException – linkage 为 null

build() → AgglomerativeClustering

用当前配置创建未拟合的聚类器。

注意

build 本身不校验,clusters 大于样本数的问题要等 fit 才抛出 IllegalArgumentException

返回

持有 clusters 与 linkage 的 AgglomerativeClustering 实例

enum AgglomerativeClustering.Linkage

层次聚类的簇间连接准则

WARD 以两组样本数加权后的均值平方距离 (ni*nj/(ni+nj))*||mi-mj||^2 作为合并代价,倾向得到大小均衡的球状簇;SINGLE、COMPLETE、AVERAGE 直接以样本间距为依据,合并后分别取两组距离的最小、最大与按样本数加权平均。

四种准则都走同一套自底向上的贪心流程:每轮选出代价最小的一对活跃簇合并,直到活跃簇数降到 clusters。簇编号按活跃簇的成员下标顺序从 0 递增,predict 对非训练样本按最近的簇均值分配。

示例
AgglomerativeClustering model = AgglomerativeClustering.builder()
        .clusters(4)
        .linkage(AgglomerativeClustering.Linkage.SINGLE)
        .build();

AgglomerativeClustering.Linkage used = model.linkage();

注意

SINGLE 对噪声敏感,容易拉出长链状簇;WARD 与 AVERAGE 更稳健但要求特征量纲一致

注意

距离固定为欧氏距离,没有可切换的度量参数

注意

该常量决定构建器的默认值(WARD),拟合后不可更改

参见:basalt.ml.AgglomerativeClustering, basalt.ml.AgglomerativeClustering.Builder

枚举成员

WARD()

最小化合并带来的簇内平方和增量

COMPLETE()

取两簇间最远点距离

AVERAGE()

取两簇间所有点对距离的均值

SINGLE()

取两簇间最近点距离

static final class DBSCAN.Builder

DBSCAN 的构建器,设置邻域半径、密度阈值与距离度量。

未显式设置时使用 eps = 0.5、minPoints = 5、DistanceMetric.EUCLIDEAN。各 setter 只赋值,参数校验集中在 build 中完成。

注意

eps 的单位与特征单位相同,特征未标准化时不同量纲的列会主导邻域判定

方法

eps(double eps) → Builder

设置邻域半径 eps。

参数
  • eps (double) – 邻域半径,须为正且有限;默认 0.5

返回

this,便于链式调用

minPoints(int minPoints) → Builder

设置核心点的最小邻域样本数。

参数
  • minPoints (int) – 阈值,须为正;默认 5,统计时包含点自身

返回

this,便于链式调用

metric(DistanceMetric metric) → Builder

设置邻域查询与预测所用的距离度量。

参数
  • metric (DistanceMetric) – 距离函数,默认 DistanceMetric.EUCLIDEAN

返回

this,便于链式调用

抛出
  • NullPointerException – metric 为 null

build() → DBSCAN

校验参数并创建 DBSCAN 实例。

返回

新的 DBSCAN 实例,尚未拟合

抛出
  • IllegalArgumentException – eps 非正或非有限,或 minPoints 非正

record DataSplit.Fold

一折的训练与测试四元组。

record 组件依次为 trainFeatures、trainTargets、testFeatures、testTargets,全部由 DataSplit.kFold 新建,与输入数据不共享存储。

测试块是洗牌顺序上的连续区间,训练块由其余区间按同一顺序拼接,因此训练集与测试集内部的行序都是洗牌后的顺序,而不是原始顺序。

注意

记录本身不可变,但持有的 Matrix 内容仍可被修改

注意

各折测试块互不重叠,并集覆盖全部行

参见:basalt.ml.DataSplit.kFold(Matrix, double[], int, long)

record DataSplit.Holdout

一次 holdout 划分的四元组。

record 组件依次为 trainFeatures、trainTargets、testFeatures、testTargets,由 DataSplit.holdout 生成,四个字段都是独立副本。

测试集行数被夹到 [1, rows-1],两侧都保证非空,因此可以直接把四个组件交给 fit 与 predict,无需再判断边界。

注意

记录本身不可变,但持有的 Matrix 内容仍可被修改

注意

划分结果只由 seed 与输入行数决定,与标签分布无关

参见:basalt.ml.DataSplit.holdout(Matrix, double[], double, long)

static final class DecisionTree.Builder

DecisionTree 的流式构造器

默认值为 maxDepth 8、minSamplesSplit 2、minSamplesLeaf 1、criterion GINI、task CLASSIFICATION、maxFeatures 0(全部特征)、bins 64、seed 42。所有 setter 返回 this,build() 统一校验并返回未拟合的估计器。

criterion 一旦被显式设置就锁定,之后调用 task() 不会改写它;未显式设置时,task(REGRESSION) 自动切到 MSE,task(CLASSIFICATION) 自动切到 GINI。

示例
DecisionTree tree = DecisionTree.builder()
        .task(TreeTask.REGRESSION)
        .maxDepth(5)
        .minSamplesSplit(4)
        .minSamplesLeaf(2)
        .maxFeatures(2)
        .bins(32)
        .seed(11L)
        .build();

注意

maxDepth 为 0 表示根节点即叶,可用于得到常数模型

注意

minSamplesSplit 的下限是 2,低于该值在 build() 时被拒绝

参见:basalt.ml.DecisionTree, basalt.ml.ImpurityCriterion, basalt.ml.TreeTask

方法

maxDepth(int maxDepth) → Builder

设置树的最大深度,默认 8

注意

深度从 0 起计,节点深度达到该值即停止分裂

参数
  • maxDepth (int) – 最大深度,须不小于 0;0 表示根节点直接成为叶

返回

this

minSamplesSplit(int minSamplesSplit) → Builder

设置允许分裂的最小节点样本数,默认 2

参数
  • minSamplesSplit (int) – 节点样本数低于该值即转为叶,须不小于 2

返回

this

minSamplesLeaf(int minSamplesLeaf) → Builder

设置每个子节点最少样本数,默认 1

注意

同时约束 fit 的入口:总样本数小于该值直接抛 IllegalArgumentException

参数
  • minSamplesLeaf (int) – 分裂后左右两侧各自的最小样本数,须不小于 1

返回

this

criterion(ImpurityCriterion criterion) → Builder

设置不纯度准则,默认 GINI

注意

调用后标记为显式设置,后续 task() 不再覆盖该准则

参数
  • criterion (ImpurityCriterion) – 准则常量,非 null;其 task() 必须与最终 task 一致

返回

this

抛出
  • NullPointerException – criterion 为 null

task(TreeTask task) → Builder

设置任务类型,默认 CLASSIFICATION

注意

未显式设置 criterion 时,同步切换为 MSE 或 GINI

参数
  • task (TreeTask) – CLASSIFICATION 或 REGRESSION,非 null

返回

this

抛出
  • NullPointerException – task 为 null

maxFeatures(int maxFeatures) → Builder

设置每次分裂的候选特征数,默认 0

注意

小于特征数时,每个节点用部分洗牌抽取子集,随机源为 seed

参数
  • maxFeatures (int) – 候选特征数;0 表示使用全部特征,大于特征数时按特征数截断

返回

this

bins(int maxBins) → Builder

设置单特征最大桶数,默认 64

参数
  • maxBins (int) – 桶数上限,取值 [2, 255]

返回

this

seed(long seed) → Builder

设置特征子采样的随机种子,默认 42

注意

行选择不受该种子影响,fit 固定使用全部行

参数
  • seed (long) – 随机种子;仅影响 maxFeatures 的特征抽取

返回

this

build() → DecisionTree

校验配置并创建估计器

返回

配置好的 DecisionTree,尚未拟合

抛出
  • IllegalArgumentException – maxDepth 小于 0、minSamplesSplit 小于 2、minSamplesLeaf 小于 1、maxFeatures 小于 0、bins 越界,或准则与任务不匹配

enum Estimators.Algorithm

门面可选算法及其任务类型。

每个常量在构造时绑定一个 Task,门面据此判断是否需要 targets,并在交叉验证时拒绝无监督算法。常量覆盖分类 8 个、回归 5 个、无监督 3 个。

RANDOM_FOREST 与 RANDOM_FOREST_REGRESSOR 共用 RandomForest 实现,靠 task 切换回归模式;两个梯度提升常量分别绑定 LOGISTIC 与 SQUARED_ERROR 目标。

注意

枚举常量名即门面的算法名,重命名会破坏调用方编译

注意

task() 是唯一的实例方法,无参无副作用

参见:basalt.ml.Estimators.Task, basalt.ml.Estimators

枚举成员

LINEAR_REGRESSION()

普通最小二乘线性回归,回归任务。

注意

对应 LinearRegression 的默认配置:lr=0.05、2000 轮

LOGISTIC_REGRESSION()

二分类逻辑回归,分类任务。

注意

标签必须是 0/1,否则 fit 抛 IllegalArgumentException

RIDGE()

L2 正则最小二乘,回归任务。

注意

对应 alpha=1.0 的默认配置

LASSO()

L1 正则最小二乘,回归任务。

注意

对应 alpha=0.1、1000 轮坐标下降的默认配置

KNN()

KNN 分类,分类任务。

注意

固定 k=5、欧氏距离

KNN_REGRESSOR()

KNN 回归,回归任务。

注意

固定 k=5、欧氏距离,预测为邻居目标的均值

DECISION_TREE()

单棵决策树分类,分类任务。

RANDOM_FOREST()

随机森林分类,分类任务。

RANDOM_FOREST_REGRESSOR()

随机森林回归,回归任务。

注意

复用 RandomForest 实现,通过 task(REGRESSION) 切换

GRADIENT_BOOSTING()

直方图梯度提升分类,分类任务。

注意

绑定 LOGISTIC 目标

GRADIENT_BOOSTING_REGRESSOR()

直方图梯度提升回归,回归任务。

注意

绑定 SQUARED_ERROR 目标

GAUSSIAN_NAIVE_BAYES()

高斯朴素贝叶斯分类,分类任务。

LINEAR_SVM()

PEGASOS 线性 SVM,分类任务。

注意

要求标签恰好两类,内部映射为 ±1

SVC()

核支持向量分类,分类任务。

注意

基于 SMO 求解,支持 LINEAR、RBF、POLY、SIGMOID 核与 One-vs-Rest 多分类

注意

门面使用默认配置:rbf(1.0) 核、C=1.0、600 轮上限

KERNEL_RIDGE()

核岭回归,回归任务。

注意

对偶方程 (K + alpha·I) 用 Cholesky 分解求解

注意

门面使用默认配置:rbf(1.0) 核、alpha=1.0

KMEANS()

K 均值聚类,无监督任务。

注意

fit 忽略 targets,交叉验证会拒绝该算法

PCA()

主成分分析,无监督任务。

注意

fit 只接收特征矩阵

KERNEL_PCA()

核主成分分析,无监督任务。

注意

默认降维到 2 个主成分、rbf(1.0) 核

注意

fit 只接收特征矩阵,transform 输出降维后的张量

DBSCAN()

密度聚类,无监督任务。

注意

门面以 null targets 调用 fit

GAUSSIAN_MIXTURE()

高斯混合模型聚类,无监督任务。

注意

EM 迭代配 K-Means++ 初始化,默认 2 个分量与对角协方差

注意

predict 返回后验概率最大的分量下标

AGGLOMERATIVE_CLUSTERING()

层次凝聚聚类,无监督任务。

注意

默认 2 个簇、WARD 连接准则

注意

连接准则支持 WARD、COMPLETE、AVERAGE、SINGLE

ISOLATION_FOREST()

隔离森林异常检测,无监督任务。

注意

predict 返回 +1 表示正常、-1 表示异常

注意

门面使用默认配置:100 棵树、maxSamples=256、contamination=0.1

KERNEL_DENSITY()

核密度估计,无监督任务。

注意

默认 GAUSSIAN 核、带宽 1.0

注意

fit 只接收特征矩阵,用 scoreSamples 评估逐样本对数似然

方法

task() → Task

返回该算法所属的任务类型。

注意

门面用它在 fit 前判断是否需要 targets

返回

构造常量时绑定的 Task

enum Estimators.Metric

交叉验证可选的评估指标。

四个常量分别转发到 Metrics.accuracy、Metrics.macroF1、Metrics.r2、Metrics.rmse,是门面与指标工具之间唯一的耦合点。

门面在累加前对 RMSE 取负号,因此四个指标的返回值都满足越大越好,交叉验证均值可以直接比较。

注意

ACCURACY 与 MACRO_F1 面向分类,R2 与 RMSE 面向回归;错配不会报错,只会得到无意义的数值

注意

指标在每折测试集上独立计算,不做加权平均

参见:basalt.ml.Metrics, basalt.ml.Estimators.crossValidate(Algorithm, Matrix, double[], int, Metric)

枚举成员

ACCURACY()

分类准确率

MACRO_F1()

宏平均 F1,各类别等权

R2()

决定系数 R²

RMSE()

均方根误差

enum Estimators.Task

算法的任务类型分类。

CLASSIFICATION 与 REGRESSION 属于有监督任务,门面 fit 要求 targets 非空;UNSUPERVISED 允许 targets 为 null,但会被 crossValidate 拒绝。

该枚举只用于门面的分支判断,不参与具体估计器的实现。

注意

三个常量之间没有层级关系,判断一律用相等比较

参见:basalt.ml.Estimators.Algorithm

枚举成员

CLASSIFICATION()

监督分类任务

REGRESSION()

监督回归任务

UNSUPERVISED()

无监督任务(聚类、降维)

record FeatureImportance.PermutationResult

置换重要性的计算结果,含逐次重复的原始分数。

三个组件依次为 importancesMean、importancesStd 与 rawImportances:前者是每个特征在所有重复上的平均分数下降,第二个是同一组重复的标准差(按总体方差计算,除以重复次数),第三个是 [特征数][重复次数] 的原始下降量。

分数下降等于基线得分减去该列被打乱后的得分,因此越大表示该特征越重要。全部数值由 FeatureImportance.permutationImportance 计算并直接放入记录,没有再做归一化。

示例
FeatureImportance.PermutationResult result = FeatureImportance.permutationImportance(
        model, features, targets, Estimators.Metric.ACCURACY, 10, 42L);

int[] order = result.rankedFeaturesDescending();
double top = result.importancesMean()[order[0]];

注意

下降为负说明打乱该列反而提升了指标,通常意味着该特征与目标无关或存在噪声

注意

rawImportances 的行对应特征列,列对应重复序号,排序与打乱都只发生在行方向上

注意

记录本身不可变,但持有的数组仍可被外部修改

参见:basalt.ml.FeatureImportance, basalt.ml.FeatureImportance.permutationImportance(Estimator, Matrix, double[], Estimators.Metric, int, long)

方法

rankedFeaturesDescending() → int[]

按平均重要性从大到小返回特征下标。

注意

只比较 importancesMean,不改动记录内的原始数组

注意

平均重要性相同的特征保持列下标升序

返回

新的 int 数组,长度为特征数,元素为列下标,最靠前的最重要

static final class GaussianMixture.Builder

GaussianMixture 的构建器。

五个超参数各有默认值:components 2、maxIterations 100、tolerance 1e-4、regCovar 1e-6、seed 42L。除 seed 外每个 setter 都会立即做正数/有限性校验,build 直接返回未拟合实例,不追加检查。

fit 阶段先用 KMeans(固定 30 轮、同一 seed)做 K-Means++ 初始化,再由 E 步与 M 步交替推进;协方差固定为对角形式,regCovar 是唯一的数值稳定手段。

示例
GaussianMixture gmm = GaussianMixture.builder()
        .components(3)
        .maxIterations(200)
        .tolerance(1e-5)
        .regCovar(1e-6)
        .seed(7L)
        .build();

gmm.fit(features);
double[] labels = gmm.predict(features);

注意

必填项:无;五个参数都可省略

注意

fit 时 components 不能超过样本数,否则抛 IllegalArgumentException

注意

seed 只影响初始化,不改变 EM 的单调性,因此相同种子下结果可复现

注意

协方差为对角矩阵,特征间相关性不会被建模

参见:basalt.ml.GaussianMixture, basalt.ml.KMeans

方法

components(int components) → Builder

设置混合成分个数,默认 2。

注意

fit 时还会校验 components 不超过样本数

参数
  • components (int) – 高斯成分个数,须为正;默认 2

返回

this,便于链式调用

抛出
  • IllegalArgumentException – components 小于等于 0

covarianceType(CovarianceType covarianceType) → Builder

指定协方差参数化,默认 FULL

参数
  • covarianceType (CovarianceType) – FULL、TIED 或 DIAG;影响存储、求值成本与 AIC 的参数计数

maxIterations(int maxIterations) → Builder

设置 EM 迭代上限,默认 100。

注意

达到上限仍未满足 tolerance 时 converged() 返回 false,参数取最后一轮的结果

参数
  • maxIterations (int) – 最大 EM 轮数,须为正;默认 100

返回

this,便于链式调用

抛出
  • IllegalArgumentException – maxIterations 小于等于 0

tolerance(double tolerance) → Builder

设置收敛阈值,默认 1e-4。

注意

判据是 |lowerBound - 上一轮 lowerBound| <= tolerance,成立即停止并标记已收敛

参数
  • tolerance (double) – 相邻两轮每样本平均对数似然之差的上限,须为正且有限;默认 1e-4

返回

this,便于链式调用

抛出
  • IllegalArgumentException – tolerance 非正或非有限

regCovar(double regCovar) → Builder

设置协方差正则项,默认 1e-6。

注意

初始化与每轮 M 步都会执行 variance = max(regCovar, variance + regCovar),避免方差塌缩到 0

注意

取值过大会把各成分的对角协方差压平,退化为球形簇

参数
  • regCovar (double) – 加到每个方差上的常数,须为正且有限;默认 1e-6

返回

this,便于链式调用

抛出
  • IllegalArgumentException – regCovar 非正或非有限

seed(long seed) → Builder

设置初始化随机种子,默认 42。

注意

种子只传给内部的 K-Means++ 初始化,EM 本身是确定性的

注意

相同 seed 与数据重复 fit 得到相同参数

参数
  • seed (long) – 随机种子,默认 42;不做取值范围校验

返回

this,便于链式调用

build() → GaussianMixture

用当前配置创建未拟合的估计器。

注意

参数校验全部在各自的 setter 内完成,build 不再重复检查

返回

持有全部超参数的 GaussianMixture 实例

enum GaussianMixture.CovarianceType

GMM 的协方差参数化方式。

FULL 为每个分量估计独立的 p×p 协方差,能表达分量内的特征相关,参数最多;TIED 让所有分量共享一个矩阵,适合各簇形状相近、单簇样本偏少的场景;DIAG 只保留对角方差,参数最少、求值最快,但无法表达相关结构。

注意

三种参数化的参数个数差异直接反映在 aic/bic 上,可用同一份数据比较拟合代价

枚举成员

FULL()

每个分量独立估计一个 p×p 协方差

TIED()

所有分量共享一个 p×p 协方差

DIAG()

每个分量只有 p 个方差(对角协方差)

static final class GaussianNaiveBayes.Builder

GaussianNaiveBayes 的构建器。

唯一参数是方差平滑系数,默认 1e-9,与 scikit-learn 的 var_smoothing 同名同义。build 只校验该系数为正且有限,其余统计量在 fit 阶段产生。

方法

varianceSmoothing(double varianceSmoothing) → Builder

设置方差平滑系数。

拟合时先乘以全体方差最大值得到 epsilon,再加到每个方差上,因此该系数对特征缩放不敏感;全部方差为 0 时 epsilon 直接取该系数本身。

参数
  • varianceSmoothing (double) – 平滑系数,须为正且有限;默认 1e-9

返回

this,便于链式调用

build() → GaussianNaiveBayes

校验参数并创建估计器。

返回

新的 GaussianNaiveBayes 实例,尚未拟合

抛出
  • IllegalArgumentException – varianceSmoothing 非正或非有限

static final class GridSearchCV.Builder

GridSearchCV 的构建器,登记参数网格与交叉验证策略。

构建器没有公开构造器,只能由 GridSearchCV.builder(estimatorFactory) 取得,估计器工厂在那一刻即为必填,空工厂直接抛 NullPointerException。参数网格用 param 逐项登记,fit 时按登记顺序做笛卡尔积。

其余四项都有默认值:scoring 为 Estimators.Metric.ACCURACY、cv 为 5、stratified 为 false、seed 为 42。build 只检查参数网格非空,配置错误主要靠各 setter 的即时校验拦下。

示例
GridSearchCV search = GridSearchCV.builder(params -> DecisionTree.builder()
                .maxDepth((Integer) params.get("maxDepth"))
                .build())
        .param("maxDepth", 3, 5, 8)
        .scoring(Estimators.Metric.ACCURACY)
        .cv(5)
        .stratified(true)
        .seed(42L)
        .build();

search.fit(features, targets);

注意

必填项:至少一次 param 调用,否则 build 抛 IllegalArgumentException

注意

estimatorFactory 已被固定,构建器无法更换工厂

注意

工厂必须按参数 Map 返回未拟合的估计器,fit 会为每个候选、每一折各调用一次

参见:basalt.ml.GridSearchCV, basalt.ml.DataSplit, basalt.ml.Estimators.Metric

方法

param(String name, Object... values) → Builder

登记一个超参数的候选值列表。

注意

同名参数再次登记会整表覆盖,而不是追加候选值

注意

多参数之间取笛卡尔积,候选总数等于各列表长度之积

参数
  • name (String) – 参数名,作为传给估计器工厂的 Map 键,非 null

  • values (Object...) – 候选值,可变参数,至少传入一个;非 null

返回

this,便于链式调用

抛出
  • NullPointerException – name 或 values 为 null

  • IllegalArgumentException – values 为空数组

scoring(Estimators.Metric scoring) → Builder

设置交叉验证打分指标,默认 ACCURACY。

注意

RMSE 在内部取负号,因此四种指标统一为越大越好,最优候选直接取均值最大者

参数
  • scoring (Estimators.Metric) – Estimators.Metric 常量,可取 ACCURACY、MACRO_F1、R2 或 RMSE,非 null

返回

this,便于链式调用

抛出
  • NullPointerException – scoring 为 null

cv(int cvFolds) → Builder

设置交叉验证折数,默认 5。

注意

每个候选都要训练 cvFolds 次,总训练次数为候选数乘以折数

参数
  • cvFolds (int) – 折数,须不小于 2;默认 5

返回

this,便于链式调用

抛出
  • IllegalArgumentException – cvFolds 小于 2

stratified(boolean stratified) → Builder

设置是否按标签分层分折,默认 false。

注意

两种划分都会先洗牌,随机源为 seed

注意

类别极不均衡时建议开启,否则某折可能缺少某个类别

参数
  • stratified (boolean) – true 时走 DataSplit.stratifiedKFold,按类别比例分折;false 时走普通 K 折

返回

this,便于链式调用

seed(long seed) → Builder

设置分折的随机种子,默认 42。

注意

只影响折划分,估计器自身的随机性需由参数网格控制

注意

给定 seed 与数据后所有候选共享同一套折,比较是公平的

参数
  • seed (long) – 随机种子,默认 42;不做取值范围校验

返回

this,便于链式调用

build() → GridSearchCV

校验参数网格并创建搜索器。

注意

构建时把参数网格复制为新的 LinkedHashMap,之后对构建器的修改不影响已创建的实例

返回

新的 GridSearchCV 实例,尚未拟合

抛出
  • IllegalArgumentException – 参数网格为空,即从未调用过 param

record GridSearchCV.CandidateResult

网格搜索中单个参数组合的交叉验证结果快照。

由 GridSearchCV.cvResults() 按网格笛卡尔积顺序返回。params 是该组合的超参数,meanScore 与 stdScore 为各折得分的均值与总体标准差(方差除以折数),foldScores 保留每折原始得分。

params 在构造时包装为不可修改的 LinkedHashMap,foldScores 直接引用传入数组,不做复制。

注意

得分方向统一为越大越好:RMSE 在累加前取负,不能与 Metrics.rmse 的原始值直接比较

注意

记录本身不校验 params 与估计器配置是否匹配,也不校验 foldScores 长度

参见:basalt.ml.GridSearchCV, basalt.ml.GridSearchCV.cvResults()

static final class HistogramGradientBoosting.Builder

HistogramGradientBoosting 的流式构造器

默认值为 algorithm XGBOOST、objective SQUARED_ERROR、iterations 100、learningRate 0.1、maxDepth 6、maxLeaves 31、bins 64、minSamplesLeaf 1、minChildWeight 1e-12、lambda 1.0、gamma 0、threads 为可用处理器数、featureFraction 1.0、validationFraction 0、earlyStoppingRounds 0、seed 42。

build() 集中校验数值范围与组合约束:早停必须配正的验证集比例,各比例参数有各自的半开区间。

示例
HistogramGradientBoosting model = HistogramGradientBoosting.builder()
        .algorithm(BoostingAlgorithm.LIGHTGBM)
        .objective(BoostingObjective.SQUARED_ERROR)
        .iterations(300)
        .learningRate(0.05)
        .maxLeaves(31)
        .minChildWeight(1e-3)
        .lambda(1.0)
        .gamma(0.0)
        .featureFraction(0.8)
        .validationFraction(0.2)
        .earlyStoppingRounds(20)
        .threads(4)
        .seed(42L)
        .build();

注意

maxLeaves 只在 LIGHTGBM 策略下生效,XGBOOST 由 maxDepth 决定形状

注意

lambda 参与叶权重与增益的分母,gamma 是每次分裂需超过的增益门槛

参见:basalt.ml.HistogramGradientBoosting, basalt.ml.BoostingAlgorithm, basalt.ml.BoostingObjective

方法

algorithm(BoostingAlgorithm algorithm) → Builder

设置生长策略,默认 XGBOOST

参数
  • algorithm (BoostingAlgorithm) – XGBOOST(深度优先)或 LIGHTGBM(叶优先),非 null

返回

this

抛出
  • NullPointerException – algorithm 为 null

objective(BoostingObjective objective) → Builder

设置目标函数,默认 SQUARED_ERROR

参数
  • objective (BoostingObjective) – SQUARED_ERROR 或 LOGISTIC,非 null

返回

this

抛出
  • NullPointerException – objective 为 null

iterations(int iterations) → Builder

设置提升轮数,默认 100

参数
  • iterations (int) – 最大树数,须大于 0;早停可能提前结束

返回

this

learningRate(double learningRate) → Builder

设置每棵树的收缩系数,默认 0.1

注意

原始得分为 baseScore 加上 learningRate 加权的各树叶值

参数
  • learningRate (double) – 叶值的缩放系数,须为正有限值

返回

this

maxDepth(int maxDepth) → Builder

设置单棵树最大深度,默认 6

参数
  • maxDepth (int) – 深度上限,须大于 0;两种生长策略都受其约束

返回

this

maxLeaves(int maxLeaves) → Builder

设置最大叶数,默认 31

注意

仅 LIGHTGBM 策略读取该值,XGBOOST 下不生效

参数
  • maxLeaves (int) – 叶数上限,须不小于 2

返回

this

bins(int binCount) → Builder

设置单特征最大桶数,默认 64

参数
  • binCount (int) – 桶数上限,取值 [2, 255]

返回

this

minSamplesLeaf(int minSamplesLeaf) → Builder

设置叶节点最小样本数,默认 1

参数
  • minSamplesLeaf (int) – 分裂后左右两侧各自的最小样本数,须大于 0

返回

this

minChildWeight(double minChildWeight) → Builder

设置子节点 hessian 和下限,默认 1e-12

注意

LOGISTIC 目标的 hessian 很小,该值决定能否继续细分

参数
  • minChildWeight (double) – 左右子节点 hessian 之和的最小值,须为非负有限值

返回

this

lambda(double lambda) → Builder

设置叶权重的 L2 正则系数,默认 1.0

参数
  • lambda (double) – 正则系数,须为非负有限值;作为 hessian 的加项出现

返回

this

gamma(double gamma) → Builder

设置分裂所需的最小增益,默认 0

注意

增益扣除 gamma 后不大于 0 的候选不产生分裂

参数
  • gamma (double) – 每次分裂从增益中扣除的阈值,须为非负有限值

返回

this

threads(int threads) → Builder

设置并行度,默认可用处理器数

参数
  • threads (int) – 工作线程数,须大于 0;同时决定直方图分块数

返回

this

featureFraction(double featureFraction) → Builder

设置每轮特征采样比例,默认 1.0

注意

按 ceil(fraction*featureCount) 取整且至少 1 个,第 i 轮用 seed + i*7919 抽取

参数
  • featureFraction (double) – 每轮参与分裂搜索的特征比例,取值 (0, 1]

返回

this

validationFraction(double validationFraction) → Builder

设置验证集比例,默认 0

注意

验证集大小取 round(rows*比例),下限 1,上限 rows-2,切分前用 seed 打乱行号

参数
  • validationFraction (double) – 切作验证集的样本比例,取值 [0, 0.5);0 表示不切分

返回

this

earlyStoppingRounds(int earlyStoppingRounds) → Builder

设置早停容忍轮数,默认 0(关闭)

注意

大于 0 时必须同时给出正的 validationFraction,否则 build() 拒绝

参数
  • earlyStoppingRounds (int) – 验证损失连续无改善的轮数上限,须不小于 0

返回

this

seed(long seed) → Builder

设置切分与特征采样种子,默认 42

参数
  • seed (long) – 随机种子;驱动验证集打乱与逐轮特征子集

返回

this

build() → HistogramGradientBoosting

校验配置并创建估计器

返回

配置好的 HistogramGradientBoosting,尚未拟合

抛出
  • IllegalArgumentException – 轮数、深度、叶数、桶数、叶样本数或线程数越界,比例超出区间,早停缺少验证集,或学习率与正则项不是合法有限值

static final class IsolationForest.Builder

IsolationForest 的流式构建器。

四个字段默认 trees=100、maxSamples=256、contamination=0.1、seed=42;setter 返回 this 以便串联,参数越界在 setter 内立即抛 IllegalArgumentException。

build() 以字段副本构造模型,不再做额外校验。maxSamples 只是上限,fit 时每棵树实际子采样 min(样本数, maxSamples) 行。

示例
IsolationForest model = IsolationForest.builder()
        .trees(200)
        .maxSamples(128)
        .contamination(0.05)
        .seed(7L)
        .build();

注意

contamination 不参与建树,只在 fit 末尾决定判定阈值:训练集异常分数升序排序后取 floor(rows × contamination) 位置

注意

树高上限为 ceil(log2(有效子采样数)),trees 与 maxSamples 直接决定内存占用与耗时

注意

构建器不是线程安全的,配置完成后应尽快 build()

参见:basalt.ml.IsolationForest, basalt.ml.IsolationForest.anomalyScore(Matrix)

方法

trees(int trees) → Builder

设置隔离树数量。

参数
  • trees (int) – 树的数量,须为正;默认 100

返回

this,便于链式调用

抛出
  • IllegalArgumentException – trees <= 0

maxSamples(int maxSamples) → Builder

设置每棵树的子采样规模上限。

fit 时实际子采样 min(样本数, maxSamples) 行,样本不足时该值被自动下调。

参数
  • maxSamples (int) – 子采样行数上限,须 >= 2;默认 256

返回

this,便于链式调用

抛出
  • IllegalArgumentException – maxSamples < 2

contamination(double contamination) → Builder

设置预期异常比例。

该值不参与建树,只在 fit 结束时用于确定阈值:训练集异常分数升序排序后取 floor(rows × contamination) 位置的值作为 threshold,decisionFunction 与 predict 据此切分。

参数
  • contamination (double) – 预期异常占比,须落在 (0, 0.5) 开区间;默认 0.1

返回

this,便于链式调用

抛出
  • IllegalArgumentException – contamination <= 0、>= 0.5 或为 NaN

seed(long seed) → Builder

设置子采样与切分点选择的随机种子。

参数
  • seed (long) – 随机种子;默认 42,相同种子与数据得到相同的树集合

返回

this,便于链式调用

build() → IsolationForest

创建 IsolationForest 实例。

注意

参数已在各 setter 中校验,此处只转调私有构造器

返回

新的 IsolationForest,尚未拟合

static final class KBinsDiscretizer.Builder

KBinsDiscretizer 的流式构建器。

三个字段默认 nBins=5、strategy=Strategy.QUANTILE、encode=Encode.ORDINAL;setter 返回 this,strategy 与 encode 在 setter 内立即做非空检查。

nBins 只决定分箱数,边界在 fit 时按策略从训练数据算出,缓存为每个特征一行的 binEdges。

示例
KBinsDiscretizer discretizer = KBinsDiscretizer.builder()
        .nBins(10)
        .strategy(KBinsDiscretizer.Strategy.QUANTILE)
        .encode(KBinsDiscretizer.Encode.ONEHOT_DENSE)
        .build();

注意

nBins < 2 在 setter 抛 IllegalArgumentException

注意

选择 ONEHOT_DENSE 后 transform 的输出列数变为输入列数 × nBins

注意

构建器不是线程安全的,配置完成后应尽快 build()

参见:basalt.ml.KBinsDiscretizer, basalt.ml.KBinsDiscretizer.Strategy, basalt.ml.KBinsDiscretizer.Encode

方法

nBins(int nBins) → Builder

设置每个特征的分箱数。

参数
  • nBins (int) – 分箱数,须 >= 2;默认 5

返回

this,便于链式调用

抛出
  • IllegalArgumentException – nBins < 2

strategy(Strategy strategy) → Builder

设置分箱边界的计算策略。

参数
  • strategy (Strategy) – Strategy 常量,默认 Strategy.QUANTILE

返回

this,便于链式调用

抛出
  • NullPointerException – strategy 为 null,在 setter 中立即抛出

encode(Encode encode) → Builder

设置输出编码方式。

参数
  • encode (Encode) – Encode 常量,默认 Encode.ORDINAL

返回

this,便于链式调用

抛出
  • NullPointerException – encode 为 null,在 setter 中立即抛出

build() → KBinsDiscretizer

创建 KBinsDiscretizer 实例。

注意

参数已在各 setter 中校验,此处只转调私有构造器

返回

新的 KBinsDiscretizer,尚未拟合

enum KBinsDiscretizer.Encode

离散化结果的编码方式。

ORDINAL 输出与输入同形的箱序号矩阵,取值 0 到 nBins-1;ONEHOT_DENSE 把每个特征展开为 nBins 列,命中箱置 1、其余置 0,输出列数为原列数 × nBins。

inverseTransform 按编码自动选择还原方式:ORDINAL 取对应箱区间的中点,ONEHOT_DENSE 取响应最大的箱中点。

注意

ONEHOT_DENSE 使用稠密矩阵,不做稀疏存储,高 nBins 时内存占用按输出列数放大

注意

predict 返回 transform 结果的展平数组,维度取决于当前编码

参见:basalt.ml.KBinsDiscretizer, basalt.ml.KBinsDiscretizer.Strategy

枚举成员

ORDINAL()

输出单个整数列,按分箱下标编码

ONEHOT_DENSE()

每个特征展开为 nBins 列稠密独热编码

enum KBinsDiscretizer.Strategy

分箱边界的计算策略。

UNIFORM 在每列最小值与最大值之间等宽切分;QUANTILE 对排序列按位置 (rows-1)·b/nBins 做线性插值取分位点;KMEANS 对单列跑 KMeans(clusters=nBins、50 轮、seed=42),再取相邻质心的中点作为边界。

三种策略都把首尾边界固定为列的最小值与最大值;常数列的内部边界全部退化为该常数。

注意

KMEANS 内部固定 50 轮与 seed=42,不受外部随机状态影响

注意

QUANTILE 的边界由训练数据决定,transform 时低于首边界或高于末边界恒落入首箱或末箱

参见:basalt.ml.KBinsDiscretizer, basalt.ml.KBinsDiscretizer.Encode, basalt.ml.KMeans

枚举成员

UNIFORM()

等宽分箱,边界均匀铺满取值区间

QUANTILE()

等频分箱,每个边界落在相同分位点

KMEANS()

对单特征做一维 KMeans,用簇中心作边界

static final class KMeans.Builder

KMeans 的构建器,设置簇数、迭代上限、收敛阈值与随机种子。

默认值:clusters = 8、maxIterations = 300、tolerance = 1e-6、seed = 42、restarts = 1、threads 取 CPU 核数。各 setter 只赋值,参数校验集中在 build 中完成。

注意

threads 只影响分配步的并行度,质心更新始终串行

方法

clusters(int clusters) → Builder

设置簇数 k。

参数
  • clusters (int) – 簇数,须为正;默认 8,拟合时不得大于样本数

返回

this,便于链式调用

maxIterations(int maxIterations) → Builder

设置单次重启的最大迭代轮数。

参数
  • maxIterations (int) – 迭代上限,须为正;默认 300

返回

this,便于链式调用

tolerance(double tolerance) → Builder

设置质心位移的收敛阈值。

停止条件为全部质心各分量位移的平方和不超过 tolerance²,即质心矩阵的 Frobenius 位移范数不超过 tolerance。

参数
  • tolerance (double) – 收敛阈值,须非负且有限;默认 1e-6

返回

this,便于链式调用

seed(long seed) → Builder

设置 K-Means++ 初始化的随机种子。

参数
  • seed (long) – 随机种子;默认 42,第 r 次重启实际使用 seed + 7919r

返回

this,便于链式调用

restarts(int restarts) → Builder

设置独立重启次数。

每次重启单独初始化并跑满迭代,最终保留惯性最小的一次,代价近似线性增长。

参数
  • restarts (int) – 重启次数,须为正;默认 1

返回

this,便于链式调用

threads(int threads) → Builder

设置分配步的并行度。

参数
  • threads (int) – 并行工作线程数,须为正;默认取可用处理器数

返回

this,便于链式调用

build() → KMeans

校验参数并创建 KMeans 实例。

返回

新的 KMeans 实例,尚未拟合

抛出
  • IllegalArgumentException – clusters、maxIterations、restarts 或 threads 非正,或 tolerance 为负或非有限

static final class KNearestNeighbors.Builder

KNearestNeighbors 的流式构建器。

两个字段在构建器内可变,setter 返回 this 以便串联。metric 在 setter 中立即做非空检查,k 的合法性推迟到 build() 校验。

默认 k=5、metric=DistanceMetric.EUCLIDEAN,与门面 Basalt.Algorithm.KNN 使用的配置一致。

示例
KNearestNeighbors model = KNearestNeighbors.builder()
        .k(3)
        .metric(DistanceMetric.EUCLIDEAN)
        .build();

注意

构建器不是线程安全的,配置完成后应尽快 build()

注意

build() 返回的实例持有字段副本,之后修改构建器不影响已建模型

参见:basalt.ml.KNearestNeighbors, basalt.ml.DistanceMetric

方法

k(int k) → Builder

设置近邻个数。

注意

此处不校验,k <= 0 在 build() 时才抛异常

注意

k 大于训练样本数在 fit 时才被发现

参数
  • k (int) – 参与投票的邻居数,必须为正;默认 5

返回

this

metric(DistanceMetric metric) → Builder

设置距离度量。

参数
  • metric (DistanceMetric) – 距离函数常量,默认 DistanceMetric.EUCLIDEAN

返回

this

抛出
  • NullPointerException – metric 为 null,在 setter 中立即抛出

build() → KNearestNeighbors

校验参数并创建分类器。

返回

新的 KNearestNeighbors,尚未拟合

抛出
  • IllegalArgumentException – k <= 0

static final class KNeighborsRegressor.Builder

KNeighborsRegressor 的流式构建器。

字段与分类版一致,metric 在 setter 中做非空检查,k 在 build() 中校验为正。默认 k=5、metric=DistanceMetric.EUCLIDEAN。

示例
KNeighborsRegressor model = KNeighborsRegressor.builder()
        .k(5)
        .metric(DistanceMetric.MANHATTAN)
        .build();

注意

构建器不是线程安全的

注意

已建模型持有字段副本,后续修改构建器无影响

参见:basalt.ml.KNeighborsRegressor, basalt.ml.DistanceMetric

方法

k(int k) → Builder

设置参与平均的邻居数。

注意

k <= 0 在 build() 时才抛异常

参数
  • k (int) – 邻居数,必须为正;默认 5

返回

this

metric(DistanceMetric metric) → Builder

设置距离度量。

参数
  • metric (DistanceMetric) – 距离函数常量,默认 DistanceMetric.EUCLIDEAN

返回

this

抛出
  • NullPointerException – metric 为 null,在 setter 中立即抛出

build() → KNeighborsRegressor

校验参数并创建回归器。

返回

新的 KNeighborsRegressor,尚未拟合

抛出
  • IllegalArgumentException – k <= 0

enum Kernel.Type

Kernel 支持的四种半正定核函数类型。

LINEAR 对应 x·y,RBF 对应 exp(-gamma·||x-y||²),POLY 对应 (gamma·x·y + coef0)^degree,SIGMOID 对应 tanh(gamma·x·y + coef0)。

枚举本身只标记求值分支,gamma、degree、coef0 三个参数由 Kernel 实例持有,通过 linear()/rbf()/poly()/sigmoid() 四个工厂方法装配。

注意

gamma 为 0 时 evaluate 会退化为 1/max(1, length),即按特征数自动取尺度

注意

POLY 的 degree 由 Kernel 构造器校验为不小于 1

注意

SIGMOID 并不保证半正定,使用时需自行确认适用性

参见:basalt.ml.Kernel

枚举成员

LINEAR()

线性核 x·y

RBF()

高斯核 exp(−gamma·‖x−y‖²)

POLY()

多项式核 (gamma·x·y + coef0)^degree

SIGMOID()

S 形核 tanh(gamma·x·y + coef0)

static final class KernelDensity.Builder

KernelDensity 的流式构建器。

只有带宽与核函数两个字段,且两个 setter 都在调用时立刻校验:bandwidth 必须是正的有限值,kernel 不可为 null。

默认 bandwidth=1.0、kernel=KernelType.GAUSSIAN,因此 builder().build() 直接得到一个可用配置,没有必填项;build() 只做字段拷贝,不做任何额外校验。

示例
KernelDensity model = KernelDensity.builder()
        .bandwidth(0.5)
        .kernel(KernelDensity.KernelType.TOPHAT)
        .build();

注意

setter 级校验意味着非法参数在链式调用中就会失败,而不是延后到 build()

注意

构建器不是线程安全的

参见:basalt.ml.KernelDensity

方法

bandwidth(double bandwidth) → Builder

设置核密度估计的带宽。

注意

带宽越小分布越尖锐,GAUSSIAN 与 TOPHAT 共用同一个带宽

参数
  • bandwidth (double) – 平滑尺度,必须为正的有限值;默认 1.0

返回

this

抛出
  • IllegalArgumentException – bandwidth 非有限或小于等于 0,在 setter 内立即抛出

kernel(KernelType kernel) → Builder

设置核函数类型。

注意

同时决定 sample 的噪声形式:GAUSSIAN 用正态噪声,TOPHAT 用均匀噪声

参数
  • kernel (KernelType) – GAUSSIAN 为高斯核,TOPHAT 为超立方体核;默认 KernelType.GAUSSIAN

返回

this

抛出
  • NullPointerException – kernel 为 null

build() → KernelDensity

创建核密度估计器。

注意

参数已在 setter 内校验,build() 不再抛异常

返回

新的 KernelDensity,尚未拟合

enum KernelDensity.KernelType

核密度估计可用的核函数类型。

GAUSSIAN 用多元高斯核,评分时按带宽归一化并做对数域稳定化;TOPHAT 用半径等于 bandwidth 的超球指示核,落在球内的样本计入密度。

类型同时影响 sample 的采样噪声:GAUSSIAN 取正态随机数乘带宽,TOPHAT 取 [-1, 1] 均匀随机数乘带宽。

注意

TOPHAT 在球内无样本可命中时,scoreSamples 返回负无穷

注意

枚举序号会写入模型文件,取值顺序参与序列化格式

参见:basalt.ml.KernelDensity

枚举成员

GAUSSIAN()

高斯核,密度处处非零

TOPHAT()

平顶核,只统计带宽内的样本

static final class KernelPCA.Builder

KernelPCA 的流式构建器。

components 与 kernel 有默认值 2 与 Kernel.rbf(1.0),两个字段都无需显式设置;rbf 与 poly 是 kernel 的便捷写法,直接替换核字段,最后调用者生效。

maxIterations=60 与 tolerance=1e-12 是 Jacobi 特征分解的内部字段,构建器没有提供对应 setter,无法从外部调整。build() 只做字段拷贝,components 不得超过样本数这一约束在 fit() 中检查。

示例
KernelPCA pca = KernelPCA.builder()
        .components(3)
        .rbf(0.5)
        .build();

注意

components 在 setter 内校验为正,越界(大于训练样本数)在 fit() 才报错

注意

poly 的 degree 小于 1 由 Kernel 构造器拒绝

注意

构建器不是线程安全的

参见:basalt.ml.KernelPCA, basalt.ml.Kernel

方法

components(int components) → Builder

设置保留的主成分个数。

注意

上限由训练样本数决定,超过时在 fit() 中抛 IllegalArgumentException

参数
  • components (int) – 降维后的维度,必须为正;默认 2

返回

this

抛出
  • IllegalArgumentException – components 小于等于 0,在 setter 内立即抛出

kernel(Kernel kernel) → Builder

直接指定核函数对象。

注意

会覆盖此前通过 rbf 或 poly 设置的核

参数
  • kernel (Kernel) – 核函数实例,不可为 null;默认 Kernel.rbf(1.0)

返回

this

抛出
  • NullPointerException – kernel 为 null

rbf(double gamma) → Builder

改用 RBF 核的便捷方法。

注意

等价于 kernel(Kernel.rbf(gamma))

参数
  • gamma (double) – 高斯核的缩放系数,必须为正的有限值

返回

this

抛出
  • IllegalArgumentException – gamma 非有限或小于等于 0

poly(int degree, double gamma, double coef0) → Builder

改用多项式核的便捷方法。

注意

等价于 kernel(Kernel.poly(degree, gamma, coef0))

参数
  • degree (int) – 多项式次数,必须大于等于 1

  • gamma (double) – 缩放系数,必须为正的有限值

  • coef0 (double) – 常数项,必须为有限值

返回

this

抛出
  • IllegalArgumentException – gamma 非有限或小于等于 0、degree 小于 1、coef0 非有限

build() → KernelPCA

创建核主成分分析估计器。

注意

build() 不做校验,components 与样本数的关系在 fit() 时检查

返回

新的 KernelPCA,尚未拟合

static final class KernelRidge.Builder

KernelRidge 的流式构建器。

两个字段都有默认值:kernel 为 Kernel.rbf(1.0),alpha 为 1.0。kernel、rbf、poly 三个 setter 写入同一个核字段,后调用者生效。

alpha 加到 Gram 矩阵对角线上形成 (K + alpha·I),由 Cholesky 分解求解对偶系数。alpha 在 setter 内校验为正的有限值,build() 只构造实例、不重复校验。

示例
KernelRidge model = KernelRidge.builder()
        .rbf(0.5)
        .alpha(0.1)
        .build();

注意

没有必填项,builder().build() 得到 RBF 核、alpha=1.0 的可用模型

注意

alpha 过小会让对偶系统接近奇异,预测对训练数据扰动敏感

注意

构建器不是线程安全的

参见:basalt.ml.KernelRidge, basalt.ml.Kernel

方法

kernel(Kernel kernel) → Builder

直接指定核函数对象。

注意

会覆盖此前通过 rbf 或 poly 设置的核

参数
  • kernel (Kernel) – 核函数实例,不可为 null;默认 Kernel.rbf(1.0)

返回

this

抛出
  • NullPointerException – kernel 为 null

rbf(double gamma) → Builder

改用 RBF 核的便捷方法。

注意

等价于 kernel(Kernel.rbf(gamma))

参数
  • gamma (double) – 高斯核的缩放系数,必须为正的有限值

返回

this

抛出
  • IllegalArgumentException – gamma 非有限或小于等于 0

poly(int degree, double gamma, double coef0) → Builder

改用多项式核的便捷方法。

注意

等价于 kernel(Kernel.poly(degree, gamma, coef0))

参数
  • degree (int) – 多项式次数,必须大于等于 1

  • gamma (double) – 缩放系数,必须为正的有限值

  • coef0 (double) – 常数项,必须为有限值

返回

this

抛出
  • IllegalArgumentException – gamma 非有限或小于等于 0、degree 小于 1、coef0 非有限

alpha(double alpha) → Builder

设置岭回归正则强度。

注意

alpha 同时起数值稳定作用,过小时对偶系统接近奇异,解对扰动敏感

参数
  • alpha (double) – 加到 Gram 矩阵对角线上的系数,必须为正的有限值;默认 1.0

返回

this

抛出
  • IllegalArgumentException – alpha 非有限或小于等于 0,在 setter 内立即抛出

build() → KernelRidge

创建核岭回归模型。

注意

参数已在 setter 内校验,build() 不再抛异常

返回

新的 KernelRidge,尚未拟合

static final class Lasso.Builder

Lasso 的流式构建器。

三个字段分别控制正则强度、迭代上限与收敛阈值,setter 只赋值,全部校验集中在 build():alpha 允许 0,maxIterations 必须为正,tolerance 必须为正。

默认 alpha=0.1、maxIterations=1000、tolerance=1e-8。

示例
Lasso model = Lasso.builder()
        .alpha(0.05)
        .maxIterations(1000)
        .tolerance(1e-8)
        .build();

注意

alpha 的尺度是按行求和的,与按均方误差定义的强度相差 n 倍

注意

构建器不是线程安全的

参见:basalt.ml.Lasso

方法

alpha(double alpha) → Builder

设置 L1 正则强度。

注意

非有限或为负在 build() 时抛 IllegalArgumentException

注意

取 0 时不再收缩系数,退化为无正则坐标下降

参数
  • alpha (double) – 软阈值阈值,作用在按行求和的尺度上;允许 0,默认 0.1

返回

this

maxIterations(int maxIterations) → Builder

设置坐标下降的最大扫描轮数。

注意

达到上限即停止,不报告未收敛

参数
  • maxIterations (int) – 整轮扫描次数上限,必须为正;默认 1000

返回

this

tolerance(double tolerance) → Builder

设置收敛阈值。

参数
  • tolerance (double) – 单轮坐标更新的最大绝对变化小于该值即停止,默认 1e-8

返回

this

抛出
  • IllegalArgumentException – build() 时非有限或小于等于 0

build() → Lasso

校验参数并创建模型。

返回

新的 Lasso,尚未拟合

抛出
  • IllegalArgumentException – alpha 非有限或为负、maxIterations <= 0、tolerance 非有限或 <= 0

record LimeExplainer.LocalExplanation

LIME 对单个样本的局部解释结果。

explainInstance 在目标样本附近采样高斯扰动、按指数欧氏核加权,拟合带 L2 的加权 Ridge 线性代理模型后返回该记录:intercept 是代理截距,featureWeights 是各特征权重,localPrediction 是代理在目标样本上的取值,modelPrediction 是原模型对该样本的预测。

r2Fidelity 是加权 R²,衡量代理对黑盒模型局部的贴合程度;topFeatures 是按 |权重 × 特征标准差| 降序排列的特征下标。

注意

featureWeights 与 topFeatures 直接引用内部数组,record 不做防御性拷贝

注意

加权总平方和不超过 1e-15 时 r2Fidelity 取 1.0,其余情况截断到不小于 0

注意

记录是只读载体,不持有对原模型或训练数据的引用

参见:basalt.ml.LimeExplainer

static final class LinearRegression.Builder

LinearRegression 的流式构建器。

四个字段控制梯度下降的步长、轮数、正则强度与是否拟合截距。setter 只赋值,校验集中在 build():learningRate 必须为正,l2 允许 0,epochs 必须为正。

默认 learningRate=0.05、epochs=2000、l2=0.0、fitIntercept=true。

示例
LinearRegression model = LinearRegression.builder()
        .learningRate(0.01)
        .epochs(500)
        .l2(0.001)
        .fitIntercept(true)
        .build();

注意

epochs 直接决定 lossHistory 的长度与 fit 的耗时

注意

构建器不是线程安全的

参见:basalt.ml.LinearRegression

方法

learningRate(double learningRate) → Builder

设置梯度下降步长。

注意

步长过大时 lossHistory 会震荡或发散,特征未标准化时尤其明显

参数
  • learningRate (double) – 每次整批更新的步长,必须为正;默认 0.05

返回

this

epochs(int epochs) → Builder

设置全批量迭代轮数。

参数
  • epochs (int) – 遍历全部样本的次数,必须为正;默认 2000

返回

this

抛出
  • IllegalArgumentException – build() 时小于等于 0

l2(double l2) → Builder

设置 L2 惩罚系数。

注意

梯度中加入 2·l2·w,截距不受影响

参数
  • l2 (double) – 权重惩罚强度,允许 0;默认 0.0(无正则)

返回

this

fitIntercept(boolean fitIntercept) → Builder

设置是否拟合截距。

参数
  • fitIntercept (boolean) – true 时更新截距,false 时截距恒为 0;默认 true

返回

this

build() → LinearRegression

校验参数并创建模型。

返回

新的 LinearRegression,尚未拟合

抛出
  • IllegalArgumentException – learningRate 非有限或 <= 0、l2 非有限或为负、epochs <= 0

static final class LinearSVM.Builder

LinearSVM 的流式构建器。

lambda 控制正则强度并间接决定步长 1/(λ·t),epochs 是遍历轮数,seed 固定洗牌随机源。setter 只赋值,build() 校验 lambda 为正、epochs 为正。

默认 lambda=0.01、epochs=20、seed=42。

示例
LinearSVM model = LinearSVM.builder()
        .lambda(0.001)
        .epochs(50)
        .seed(7L)
        .build();

注意

相同 seed 与相同数据得到完全一致的训练轨迹

注意

构建器不是线程安全的

参见:basalt.ml.LinearSVM

方法

lambda(double lambda) → Builder

设置正则强度。

注意

值越小正则越弱、早期有效步长越大,收敛更快但更易震荡

参数
  • lambda (double) – L2 正则系数,步长按 1/(lambda*t) 计算,必须为正;默认 0.01

返回

this

epochs(int epochs) → Builder

设置遍历训练集的轮数。

注意

累计步数 t 跨轮递增,不随 epoch 重置

参数
  • epochs (int) – 完整扫描次数,必须为正;默认 20

返回

this

抛出
  • IllegalArgumentException – build() 时小于等于 0

seed(long seed) → Builder

设置洗牌随机种子。

注意

只影响样本访问顺序,不影响权重初值(恒为零)

参数
  • seed (long) – 每轮洗牌所用 Random 的种子;默认 42

返回

this

build() → LinearSVM

校验参数并创建模型。

返回

新的 LinearSVM,尚未拟合

抛出
  • IllegalArgumentException – lambda 非有限或 <= 0、epochs <= 0

static final class LogisticRegression.Builder

LogisticRegression 的流式构建器。

三个字段控制步长、轮数与 L2 强度。setter 只赋值,build() 校验 learningRate 为正、l2 非负、epochs 为正。

默认 learningRate=0.1、epochs=2000、l2=0.0。

示例
LogisticRegression model = LogisticRegression.builder()
        .learningRate(0.1)
        .epochs(2000)
        .l2(0.001)
        .build();

注意

没有 fitIntercept 开关,截距始终参与训练且不受正则

注意

构建器不是线程安全的

参见:basalt.ml.LogisticRegression

方法

learningRate(double learningRate) → Builder

设置梯度下降步长。

注意

步长过大时交叉熵可能不降反升

参数
  • learningRate (double) – 每次整批更新的步长,必须为正;默认 0.1

返回

this

epochs(int epochs) → Builder

设置全批量迭代轮数。

参数
  • epochs (int) – 遍历全部样本的次数,必须为正;默认 2000

返回

this

抛出
  • IllegalArgumentException – build() 时小于等于 0

l2(double l2) → Builder

设置 L2 惩罚系数。

注意

以 2·l2·w 加入权重梯度,截距不受惩罚

参数
  • l2 (double) – 权重惩罚强度,允许 0;默认 0.0(无正则)

返回

this

build() → LogisticRegression

校验参数并创建模型。

返回

新的 LogisticRegression,尚未拟合

抛出
  • IllegalArgumentException – learningRate 非有限或 <= 0、l2 非有限或为负、epochs <= 0

static final class MinMaxScaler.Builder

MinMaxScaler 的流式构建器。

featureRange 决定缩放的目标区间,clip 决定是否把越界值截断回该区间。两个字段都有默认值,没有必填项。

默认 featureMin=0.0、featureMax=1.0、clip=false。featureRange 在 setter 内校验两端有限且 max > min,build() 只做字段拷贝。

示例
MinMaxScaler scaler = MinMaxScaler.builder()
        .featureRange(-1.0, 1.0)
        .clip(true)
        .build();

注意

常数特征列(极差不超过 1e-12)在 fit 时以 1.0 作分母,输出恒等于 featureMin

注意

clip 只影响 transform,不改变 fit 得到的 scale 与 minOffset

注意

构建器不是线程安全的

参见:basalt.ml.MinMaxScaler

方法

featureRange(double min, double max) → Builder

设置缩放的目标区间。

注意

区间可取负值或跨越 0,只要求 max > min

参数
  • min (double) – 目标区间下界,必须为有限值;默认 0.0

  • max (double) – 目标区间上界,必须为有限值且大于 min;默认 1.0

返回

this

抛出
  • IllegalArgumentException – min 或 max 非有限,或 max 不大于 min,在 setter 内立即抛出

clip(boolean clip) → Builder

设置是否把结果裁剪到目标区间。

注意

只在 transform 生效,inverseTransform 直接按逆公式还原

参数
  • clip (boolean) – true 时 transform 将每个值截断到 [featureMin, featureMax];默认 false

返回

this

build() → MinMaxScaler

创建最小最大缩放器。

注意

featureRange 已在 setter 内校验,build() 不再检查

返回

新的 MinMaxScaler,尚未拟合

static final class OneHotEncoder.Builder

OneHotEncoder 的流式构建器。

handleUnknown 决定 transform 遇到训练时未见类别怎么办,categoricalColumns 指定哪些列按类别展开,其余列原样透传。

默认 handleUnknown=ERROR、categoricalColumns=null,后者表示所有列都按类别处理。两个字段都可省略;build() 不做校验,列下标是否越界要到 fit() 才检查。

示例
OneHotEncoder encoder = OneHotEncoder.builder()
        .handleUnknown(OneHotEncoder.HandleUnknown.IGNORE)
        .categoricalColumns(0, 2)
        .build();

注意

categoricalColumns 在 setter 内克隆,调用方之后修改原数组不会影响编码器

注意

IGNORE 下未见类别输出全零指示向量,inverseTransform 会把它还原为 NaN

注意

构建器不是线程安全的

参见:basalt.ml.OneHotEncoder

方法

handleUnknown(HandleUnknown handleUnknown) → Builder

设置未见类别的处理策略。

注意

只在 transform 阶段生效,fit 不受影响

参数
  • handleUnknown (HandleUnknown) – ERROR 抛异常,IGNORE 输出全零指示;默认 HandleUnknown.ERROR

返回

this

抛出
  • NullPointerException – handleUnknown 为 null

categoricalColumns(int... columns) → Builder

指定按类别编码的列下标。

注意

setter 内克隆数组,调用方后续修改入参不影响构建器

注意

下标越界在 fit() 时抛 IllegalArgumentException,未指定的列原样透传

参数
  • columns (int...) – 类别列下标,从 0 开始;不调用或传 null 表示所有列都按类别处理

返回

this

build() → OneHotEncoder

创建独热编码器。

注意

类别集合在 fit() 时按取值升序收集

返回

新的 OneHotEncoder,尚未拟合

enum OneHotEncoder.HandleUnknown

transform 遇到未见类别时的处理策略。

ERROR 表示训练期未出现的类别值在 transform 阶段直接抛 IllegalArgumentException;IGNORE 表示为其输出全零指示向量,不报错。

该开关只影响 transform。fit 阶段按每一列的排序去重结果建立类别表,不涉及未见类别;inverseTransform 对全零行返回 NaN。

示例
OneHotEncoder encoder = OneHotEncoder.builder()
        .handleUnknown(OneHotEncoder.HandleUnknown.IGNORE)
        .build();

注意

ERROR 的校验逐行逐列进行,首个未见值即中断,不返回部分结果

注意

IGNORE 下未见类别与全零行无法区分,逆变换统一得到 NaN

参见:basalt.ml.OneHotEncoder, basalt.ml.OneHotEncoder.Builder

枚举成员

ERROR()

transform 时遇到未见类别抛 IllegalArgumentException

IGNORE()

未见类别编码为全 0 行

static final class PCA.Builder

PCA 的构建器,设置分量数、求解器、扫描上限与白化开关。

默认值:components = 2、solver = AUTO、maxIterations = 60、tolerance = 1e-12、whiten = false。各 setter 只赋值,参数校验集中在 build 中完成。

注意

components 的上界依赖数据形状,只能在 fit 阶段校验

方法

components(int components) → Builder

设置保留的主成分个数。

参数
  • components (int) – 分量数,须为正;默认 2,拟合时不得大于 min(样本数, 特征数)

返回

this,便于链式调用

solver(EigenSolver solver) → Builder

设置特征分解求解器。

参数
  • solver (EigenSolver) – 求解器,默认 EigenSolver.AUTO

返回

this,便于链式调用

抛出
  • NullPointerException – solver 为 null

maxIterations(int maxIterations) → Builder

设置 Jacobi 扫描的最大轮数。

参数
  • maxIterations (int) – 扫描上限,须为正;默认 60

返回

this,便于链式调用

tolerance(double tolerance) → Builder

设置 Jacobi 扫描的收敛阈值。

收敛判据为 sqrt(Σ a_pq²) 不超过 tolerance · max(1, ‖A‖_F),其中求和覆盖全部非对角元素。

参数
  • tolerance (double) – 收敛阈值,须为正且有限;默认 1e-12

返回

this,便于链式调用

whiten(boolean whiten) → Builder

设置是否白化投影结果。

白化把每个投影除以其主成分标准差,使各分量方差为 1;逆变换会乘回同一标准差。

参数
  • whiten (boolean) – true 表示白化;默认 false

返回

this,便于链式调用

build() → PCA

校验参数并创建 PCA 实例。

返回

新的 PCA 实例,尚未拟合

抛出
  • IllegalArgumentException – components 或 maxIterations 非正,或 tolerance 非正或非有限

static final class Pipeline.Builder

Pipeline 的构造器,按序追加步骤并挂接末端估计器。

初始状态为空步骤列表、无末端估计器。addStep 负责累积变换器,estimator 设置唯一的末端估计器;至少要有其中一项才能通过 build。

build() 只做空管线校验,其余约束推迟到运行期:步骤名重复、估计器不支持持久化都在后续调用或写入时才暴露。

示例
Pipeline pipeline = Pipeline.builder()
        .addStep(PolynomialFeatures.builder().degree(2).build())
        .estimator("ridge", Ridge.builder().alpha(1.0).build())
        .build();

注意

步骤顺序即执行顺序,transform 正向、inverseTransform 反向

注意

未命名步骤自动取 step0、step1 等名称

注意

构建器不是线程安全的

参见:basalt.ml.Pipeline, basalt.ml.Pipeline.Step

方法

addStep(String name, Transformer transformer) → Builder

按给定名称追加一个变换步骤。

步骤按调用顺序排列,fit 时依次 fitTransform,transform 与 predict 时依次 transform,inverseTransform 时逆序回放。

注意

重名不会被拒绝,namedSteps() 中后写入者覆盖先写入者

参数
  • name (String) – 步骤名,用于 namedSteps() 与持久化;不可为 null

  • transformer (Transformer) – 变换器实例;不可为 null

返回

this,便于链式调用

抛出
  • NullPointerException – name 或 transformer 为 null

addStep(Transformer transformer) → Builder

追加步骤并自动命名为 stepN。

名称取 "step" 拼上追加前的步骤数,首个步骤为 step0,其后依次递增。

参数
  • transformer (Transformer) – 变换器实例;不可为 null

返回

this,便于链式调用

抛出
  • NullPointerException – transformer 为 null

estimator(String name, Estimator estimator) → Builder

设置具名末端估计器。

末端估计器在所有变换步骤之后拟合与预测,并作为 namedSteps() 的最后一项。

注意

重复调用会整体替换前一次的末端估计器与名称

参数
  • name (String) – 估计器名称,用于 namedSteps() 与持久化;不可为 null

  • estimator (Estimator) – 末端估计器;不可为 null

返回

this,便于链式调用

抛出
  • NullPointerException – name 或 estimator 为 null

estimator(Estimator estimator) → Builder

设置末端估计器,名称固定为 estimator。

参数
  • estimator (Estimator) – 末端估计器;不可为 null

返回

this,便于链式调用

抛出
  • NullPointerException – estimator 为 null

build() → Pipeline

校验并构建流水线。

注意

只校验非空,不检查步骤重名,也不检查估计器是否实现 Persistable

返回

配置好的 Pipeline,尚未拟合

抛出
  • IllegalArgumentException – 既没有步骤也没有末端估计器

record Pipeline.Step

流水线中的具名步骤:名称与变换器的不可变组合。

紧凑构造器对 name 与 transformer 做非空校验,两者一旦写入即不可更改。步骤在列表中按插入顺序存放,Pipeline 依此顺序正向执行变换、反向执行逆变换。

steps() 返回不可变列表,元素即 Step 记录本身。

示例
Pipeline.Step step = new Pipeline.Step("poly", PolynomialFeatures.builder().build());

注意

name 参与 namedSteps() 的键与 .bsl 持久化,需自行保证唯一

注意

name 或 transformer 为 null 时构造抛 NullPointerException

参见:basalt.ml.Pipeline, basalt.ml.Pipeline.Builder

static final class PolynomialFeatures.Builder

PolynomialFeatures 的构造器,设置阶数与偏置项。

默认 degree = 2、interactionOnly = false、includeBias = true。degree 在 setter 调用时校验,build() 只做装配,没有额外校验。

输出列的组合集合在 fit 阶段按输入特征数生成,因此构建器本身不持有任何依赖数据的形状信息。

示例
PolynomialFeatures poly = PolynomialFeatures.builder()
        .degree(3)
        .interactionOnly(false)
        .includeBias(true)
        .build();

注意

列数随 degree 与特征数组合增长,高阶时输出维度会迅速膨胀

注意

interactionOnly 与 includeBias 均无取值范围约束

注意

构建器不是线程安全的

参见:basalt.ml.PolynomialFeatures

方法

degree(int degree) → Builder

设置多项式最高阶数,默认 2。

阶数决定单项式的最大总次数,从 1 次逐层生成到该阶。

注意

该校验在 setter 内完成,不走 build()

参数
  • degree (int) – 最高阶数,须不小于 1;默认 2

返回

this,便于链式调用

抛出
  • IllegalArgumentException – degree 小于 1

interactionOnly(boolean interactionOnly) → Builder

设置是否只生成纯交互项,默认 false。

开启后每个特征在同一次单项式中最多出现一次,输出仅含不同特征的乘积;关闭时允许特征重复,从而包含平方及更高次项。

注意

真实输出列数在 fit 时按输入特征数展开,构建阶段无法确定

参数
  • interactionOnly (boolean) – true 表示只生成不同特征的乘积;默认 false

返回

this,便于链式调用

includeBias(boolean includeBias) → Builder

设置是否输出常数列,默认 true。

开启时在所有单项式之前插入一列取值恒为 1 的偏置列(对应空组合),关闭时输出从 1 次项开始。

参数
  • includeBias (boolean) – true 表示首列输出常数 1;默认 true

返回

this,便于链式调用

build() → PolynomialFeatures

创建 PolynomialFeatures 实例。

注意

不做参数校验,degree 的合法性已在 setter 中过滤

返回

新的 PolynomialFeatures,尚未拟合

static final class RFE.Builder

RFE 的构造器,设置保留特征数与淘汰步长。

默认 nFeaturesToSelect = 2、step = 1。估计器不直接传入,而是由 builder(Supplier) 提供的工厂在每轮消除与最终拟合时各创建一个新实例,保证每轮从干净状态训练。

两个 setter 在调用时校验下界,nFeaturesToSelect 的上界与估计器能力(featureImportances() 或线性 weights())要等 fit 才能判定。

示例
RFE rfe = RFE.builder(() -> Ridge.builder().build())
        .nFeaturesToSelect(3)
        .step(1)
        .build();

注意

工厂会在 fit 过程中被反复调用,其返回的估计器必须可重复构造

注意

不支持重要性或线性权重的估计器在 fit 时抛 IllegalArgumentException

注意

构建器不是线程安全的

参见:basalt.ml.RFE, basalt.ml.SelectKBest

方法

nFeaturesToSelect(int nFeaturesToSelect) → Builder

设置最终保留的特征数,默认 2。

注意

上界依赖数据列数,只能在 fit 阶段校验

参数
  • nFeaturesToSelect (int) – 保留特征数,须为正;默认 2,fit 时不得大于输入列数

返回

this,便于链式调用

抛出
  • IllegalArgumentException – nFeaturesToSelect 小于等于 0

step(int step) → Builder

设置每轮淘汰的特征数,默认 1。

每轮实际淘汰 min(step, 剩余特征数 − 保留特征数) 个重要性最低的特征,最后不足一整步时按剩余量截断。

注意

step 越大,迭代轮数与估计器拟合次数越少,但排名粒度越粗

参数
  • step (int) – 每轮淘汰数,须为正;默认 1

返回

this,便于链式调用

抛出
  • IllegalArgumentException – step 小于等于 0

build() → RFE

创建 RFE 实例。

注意

不做参数校验,两个 setter 已在调用时过滤非法值

返回

新的 RFE,尚未拟合

static final class RandomForest.Builder

RandomForest 的流式构造器

默认值为 trees 100、maxDepth 8、minSamplesLeaf 1、maxFeatures 0(按平方根解析)、bins 64、threads 为可用处理器数、seed 42、task CLASSIFICATION、oob 关闭。build() 校验后返回未拟合的森林。

maxFeatures 的 0 值不在构造期解析,而是在 fit 时按 max(1, sqrt(featureCount)) 计算,因此特征数由训练数据决定。

示例
RandomForest forest = RandomForest.builder()
        .trees(200)
        .maxDepth(10)
        .minSamplesLeaf(2)
        .maxFeatures(3)
        .bins(64)
        .threads(8)
        .seed(42L)
        .task(TreeTask.REGRESSION)
        .oob(true)
        .build();

注意

threads 决定 ForkJoinPool 的并行度,须大于 0

注意

打开 oob 会增加每棵树一次全量推理的开销,并受 800 万次树-行预测上限约束

参见:basalt.ml.RandomForest, basalt.ml.TreeTask

方法

trees(int treeCount) → Builder

设置树的数量,默认 100

注意

树数与行数的乘积决定 OOB 评估的规模上限

参数
  • treeCount (int) – 树数,须大于 0

返回

this

maxDepth(int maxDepth) → Builder

设置每棵树的最大深度,默认 8

参数
  • maxDepth (int) – 深度上限,须不小于 0;0 表示单叶

返回

this

minSamplesLeaf(int minSamplesLeaf) → Builder

设置叶节点最小样本数,默认 1

参数
  • minSamplesLeaf (int) – 分裂后左右两侧各自的最小样本数,须大于 0

返回

this

maxFeatures(int maxFeatures) → Builder

设置每次分裂的候选特征数,默认 0

注意

大于特征数时由 DecisionTree 的候选抽取按特征数截断

参数
  • maxFeatures (int) – 候选特征数;0 表示在 fit 时解析为 max(1, sqrt(featureCount))

返回

this

bins(int maxBins) → Builder

设置单特征最大桶数,默认 64

注意

全森林共用一份分箱,该值只在 fit 开始时使用一次

参数
  • maxBins (int) – 桶数上限,取值 [2, 255]

返回

this

threads(int threads) → Builder

设置拟合并行度,默认可用处理器数

参数
  • threads (int) – 工作线程数,须大于 0

返回

this

seed(long seed) → Builder

设置随机种子,默认 42

注意

自助采样序列由 seed + i*1000003 驱动,与树的特征种子相互独立

参数
  • seed (long) – 基础种子;第 i 棵树的种子为 seed + i*31

返回

this

task(TreeTask task) → Builder

设置任务类型,默认 CLASSIFICATION

参数
  • task (TreeTask) – CLASSIFICATION 或 REGRESSION,非 null

返回

this

抛出
  • NullPointerException – task 为 null

oob(boolean oob) → Builder

设置是否计算袋外分数,默认关闭

注意

打开后 treeCount*rows 超过 800 万,fit 抛 IllegalArgumentException

注意

关闭时 oobScore() 抛 IllegalStateException

参数
  • oob (boolean) – true 时每棵树额外对全量矩阵推理并累计袋外预测

返回

this

build() → RandomForest

校验配置并创建森林

返回

配置好的 RandomForest,尚未拟合

抛出
  • IllegalArgumentException – 树数不大于 0、maxDepth 小于 0、minSamplesLeaf 不大于 0、maxFeatures 小于 0、threads 不大于 0,或 bins 越界

static final class RandomizedSearchCV.Builder

随机搜索的构造器,登记参数分布与分折策略。

默认 nIter = 10、scoring = ACCURACY、cv = 5 折、stratified 关闭、seed = 42,分布表为空。四个 param* 方法在登记时即完成取值校验,把抽样函数写入按插入顺序保存的映射;build() 只要求至少登记一个分布。

fit 每轮按登记顺序对每个分布抽一次,全部用同一个 Random(seed) 驱动;分层开关决定采用分层 K 折还是普通 K 折,折划分同样使用该种子。每轮对全部折拟合并以折均值为该组参数的得分。

示例
RandomizedSearchCV search = RandomizedSearchCV.builder(
                params -> Ridge.builder().alpha((Double) params.get("alpha")).build())
        .paramLogUniform("alpha", 1e-3, 10.0)
        .nIter(20)
        .scoring(Estimators.Metric.R2)
        .cv(5)
        .seed(42L)
        .build();

注意

同名参数重复登记会覆盖旧分布,但在映射中保留首次登记的位置

注意

paramUniform、paramLogUniform、paramIntRange 不校验 name 是否为 null,paramChoices 会校验

注意

均值并列时保留先出现的那一组,比较使用严格大于

注意

估计器工厂在每折与最终重训时都会被调用

参见:basalt.ml.RandomizedSearchCV, basalt.ml.RandomizedSearchCV.ParameterSampler, basalt.ml.GridSearchCV

方法

paramChoices(String name, Object... choices) → Builder

登记离散候选列表,等概率有放回抽取。

每轮用共享随机源取一个下标,同一次搜索内同一候选值可以被重复抽中。候选数组在登记时克隆,之后修改原数组不影响抽样结果。

参数
  • name (String) – 参数名,须非 null

  • choices (Object...) – 候选值数组,至少一个元素,元素可为 null

返回

this,便于链式调用

抛出
  • NullPointerException – name 或 choices 为 null

  • IllegalArgumentException – choices 长度为 0

paramUniform(String name, double low, double high) → Builder

登记 [low, high) 上的均匀分布。

抽样值为 low + U(0,1) · (high − low),区间上界取不到。

注意

不校验 name 是否为 null,也不校验端点是否有限

参数
  • name (String) – 参数名

  • low (double) – 区间下界,含

  • high (double) – 区间上界,不含,须严格大于 low

返回

this,便于链式调用

抛出
  • IllegalArgumentException – high 不大于 low

paramLogUniform(String name, double low, double high) → Builder

登记对数均匀分布。

先在 log(low) 与 log(high) 之间均匀取值,再取指数还原,适合同一参数跨数量级搜索的场景。

参数
  • name (String) – 参数名

  • low (double) – 区间下界,须严格大于 0

  • high (double) – 区间上界,须严格大于 low

返回

this,便于链式调用

抛出
  • IllegalArgumentException – low 不大于 0,或 high 不大于 low

paramIntRange(String name, int lowInclusive, int highInclusive) → Builder

登记闭区间上的均匀整数分布。

取值覆盖 lowInclusive 到 highInclusive 的全部整数,两端均可取到。

参数
  • name (String) – 参数名

  • lowInclusive (int) – 闭区间下界

  • highInclusive (int) – 闭区间上界,须不小于下界

返回

this,便于链式调用

抛出
  • IllegalArgumentException – highInclusive 小于 lowInclusive

nIter(int nIter) → Builder

设置抽样迭代次数,默认 10。

注意

每轮对全部已登记分布各抽一次,并完成一整轮 cross-validation

参数
  • nIter (int) – 迭代轮数,须为正

返回

this,便于链式调用

抛出
  • IllegalArgumentException – nIter 小于等于 0

scoring(Estimators.Metric scoring) → Builder

设置评分指标,默认 ACCURACY。

注意

搜索统一取折均值最大者,RMSE 这类越小越好的指标需自行留意方向

参数
  • scoring (Estimators.Metric) – 评分指标,可选 ACCURACY、MACRO_F1、R2、RMSE;默认 ACCURACY

返回

this,便于链式调用

抛出
  • NullPointerException – scoring 为 null

cv(int cvFolds) → Builder

设置交叉验证折数,默认 5。

参数
  • cvFolds (int) – 折数,须不小于 2

返回

this,便于链式调用

抛出
  • IllegalArgumentException – cvFolds 小于 2

stratified(boolean stratified) → Builder

设置是否分层分折,默认关闭。

开启时按目标值分层划分折,关闭时使用普通 K 折;两种方式都带同一个 seed 做洗牌。

参数
  • stratified (boolean) – true 表示分层 K 折;默认 false

返回

this,便于链式调用

seed(long seed) → Builder

设置随机种子,默认 42。

注意

同一 seed 与同一数据下重复 fit 得到相同的折划分与抽样序列

参数
  • seed (long) – 随机种子,同时驱动分折与参数抽样

返回

this,便于链式调用

build() → RandomizedSearchCV

校验并创建搜索器。

注意

nIter、cv、scoring 已在 setter 中校验,build 只检查分布表非空

返回

新的 RandomizedSearchCV,尚未拟合

抛出
  • IllegalArgumentException – 未登记任何参数分布

interface RandomizedSearchCV.ParameterSampler

参数分布的抽样接口,单方法返回一个参数值。

函数式接口,唯一方法 sample(Random) 从外部传入的随机源抽取一个取值。Builder 的 paramChoices、paramUniform、paramLogUniform、paramIntRange 都以此为载体把分布登记进映射,fit 时每轮按登记顺序各调用一次。

随机源由 fit 统一创建并顺序传递,因此同一 seed 下抽样序列可复现。

注意

实现不应自行播种或缓存随机源,否则各轮取值会退化为重复

注意

返回值直接放进参数映射交给估计器工厂,fit 不做类型转换或校验

注意

抽样是有放回的,同一次搜索内可能抽到完全相同的参数组合

参见:basalt.ml.RandomizedSearchCV, basalt.ml.RandomizedSearchCV.Builder

static final class Ridge.Builder

Ridge 的流式构建器。

alpha 是加在 Gram 矩阵对角线上的正则量,fitIntercept 决定是否中心化并反推截距。setter 只赋值,build() 只校验 alpha 为正。

默认 alpha=1.0、fitIntercept=true。

示例
Ridge model = Ridge.builder()
        .alpha(0.1)
        .fitIntercept(true)
        .build();

注意

alpha 不允许为 0;需要无正则解时改用 LinearRegression

注意

构建器不是线程安全的

参见:basalt.ml.Ridge

方法

alpha(double alpha) → Builder

设置 L2 正则强度。

注意

尺度是按行求和的,未除以样本数

参数
  • alpha (double) – 加到 Gram 对角线上的值,必须为正;默认 1.0

返回

this

抛出
  • IllegalArgumentException – build() 时非有限或小于等于 0

fitIntercept(boolean fitIntercept) → Builder

设置是否中心化并拟合截距。

注意

为 false 时截距恒为 0.0,且 alpha 会压缩未中心化的系数

参数
  • fitIntercept (boolean) – true 时中心化特征与目标并反推截距,false 时直接解原始正规方程;默认 true

返回

this

build() → Ridge

校验参数并创建模型。

返回

新的 Ridge,尚未拟合

抛出
  • IllegalArgumentException – alpha 非有限或小于等于 0

static final class SVC.Builder

SVC 的构造器,设置核函数、惩罚系数与 SMO 参数。

默认 kernel = Kernel.rbf(1.0)、c = 1.0、tolerance = 1e-4、maxIterations = 600、seed = 42。核函数只有一个字段,kernel、rbf、poly、linear 四个 setter 互相覆盖。

c、tolerance、maxIterations 以及 rbf/poly 的 gamma 在 setter 调用时即校验并抛异常;build() 只把五个字段装进实例,没有额外检查。

示例
SVC model = SVC.builder()
        .rbf(0.5)
        .c(1.0)
        .tolerance(1e-4)
        .maxIterations(600)
        .seed(42L)
        .build();

注意

kernel 与 rbf、poly、linear 写同一字段,最终生效的是最后一次调用

注意

poly 的 degree 下界与 coef0 有限性由 Kernel 构造器校验

注意

松容差加小迭代上限会得到欠拟合的解,且不会报错

参见:basalt.ml.SVC, basalt.ml.Kernel

方法

kernel(Kernel kernel) → Builder

设置核函数对象,默认 rbf(1.0)。

注意

与 rbf、poly、linear 共用同一字段,后调用者覆盖先调用者

参数
  • kernel (Kernel) – 核函数实例,不可为 null;默认 Kernel.rbf(1.0)

返回

this,便于链式调用

抛出
  • NullPointerException – kernel 为 null

rbf(double gamma) → Builder

改用 RBF 核并设置 gamma。

核函数为 K(x, y) = exp(−gamma · ‖x − y‖²),gamma 越大决策边界越贴合训练点。

参数
  • gamma (double) – RBF 的带宽倒数,须为正且有限

返回

this,便于链式调用

抛出
  • IllegalArgumentException – gamma 非有限或小于等于 0

poly(int degree, double gamma, double coef0) → Builder

改用多项式核并设置阶数、gamma 与常数项。

核函数为 K(x, y) = (gamma · x·y + coef0)^degree,coef0 控制低阶项的相对权重。

参数
  • degree (int) – 多项式阶数,须不小于 1

  • gamma (double) – 内积缩放系数,须为正且有限

  • coef0 (double) – 常数项,须有限,可为负

返回

this,便于链式调用

抛出
  • IllegalArgumentException – gamma 非正或非有限,degree 小于 1,或 coef0 非有限

linear() → Builder

改用线性核。

核函数退化为内积 K(x, y) = x·y,不引入 gamma、degree、coef0 等超参数。

返回

this,便于链式调用

probability(boolean probability) → Builder

开启 Platt 概率校准,默认关闭

参数
  • probability (boolean) – true 时 fit 末尾为每个二分类子问题额外拟合一组 A、B

c(double c) → Builder

设置惩罚系数 C,默认 1.0。

C 同时充当每个拉格朗日乘子的上界,值越大对间隔违例越不宽容,越容易过拟合。

参数
  • c (double) – 惩罚系数,须为正且有限

返回

this,便于链式调用

抛出
  • IllegalArgumentException – c 非有限或小于等于 0

tolerance(double tolerance) → Builder

设置 SMO 的 KKT 违例容差,默认 1e-4。

仅当样本的 y·E 超出 ±tolerance 且乘子未顶到 0 或 C 时才触发一次乘子更新,容差越小收敛越慢、解越精确。

参数
  • tolerance (double) – 违例阈值,须为正且有限

返回

this,便于链式调用

抛出
  • IllegalArgumentException – tolerance 非有限或小于等于 0

maxIterations(int maxIterations) → Builder

设置每个二分类子问题的最大迭代轮数,默认 600。

达到上限即停止,即使尚未满足收敛条件;连续 5 轮扫描都没有乘子更新时也会提前退出。

注意

多分类按 One-vs-Rest 展开,每个子问题独立计数

参数
  • maxIterations (int) – 迭代上限,须为正

返回

this,便于链式调用

抛出
  • IllegalArgumentException – maxIterations 小于等于 0

seed(long seed) → Builder

设置随机种子,默认 42。

种子只用于第二个乘子的启发式挑选:15% 的概率改为随机选点,其余情况取误差差最大的点。

注意

同一 seed 下训练结果可复现

参数
  • seed (long) – 基础种子;第 m 个子问题使用 seed + m·101

返回

this,便于链式调用

build() → SVC

创建 SVC 实例。

注意

不做额外校验,全部约束已在各 setter 中完成

返回

新的 SVC,尚未拟合

static final class SelectKBest.Builder

SelectKBest 的构造器,设置保留数与评分函数。

默认 k = 5、scoreFunc = F_CLASSIF。两个 setter 在调用时校验下界与空值,build() 只做装配。

k 的上界与 CHI2 的非负性要求都依赖训练数据,推迟到 fit 阶段才校验;不满足时抛 IllegalArgumentException。

示例
SelectKBest selector = SelectKBest.builder()
        .k(10)
        .scoreFunc(SelectKBest.ScoreFunc.F_CLASSIF)
        .build();

注意

分数并列时按列索引升序优先,selectedIndices() 最终按升序返回

注意

F_CLASSIF 与 CHI2 把目标视为离散类别,F_REGRESSION 把目标视为连续值

注意

构建器不是线程安全的

参见:basalt.ml.SelectKBest, basalt.ml.RFE

方法

k(int k) → Builder

设置保留的特征数,默认 5。

注意

上界依赖数据列数,只能在 fit 阶段校验

参数
  • k (int) – 保留特征数,须为正;默认 5,fit 时不得大于输入列数

返回

this,便于链式调用

抛出
  • IllegalArgumentException – k 小于等于 0

scoreFunc(ScoreFunc scoreFunc) → Builder

设置评分函数,默认 F_CLASSIF。

F_CLASSIF 用单因素方差分析衡量类间差异,F_REGRESSION 用相关系数换算 F 值,CHI2 用列联表的卡方统计量。

注意

CHI2 要求全部特征非负,否则 fit 抛 IllegalArgumentException

参数
  • scoreFunc (ScoreFunc) – F_CLASSIF、F_REGRESSION 或 CHI2;默认 F_CLASSIF

返回

this,便于链式调用

抛出
  • NullPointerException – scoreFunc 为 null

build() → SelectKBest

创建 SelectKBest 实例。

注意

不做参数校验,k 与 scoreFunc 已在 setter 中过滤

返回

新的 SelectKBest,尚未拟合

enum SelectKBest.ScoreFunc

特征打分的统计检验:分类 F、回归 F、卡方

F_CLASSIF 把 targets 的每个不同取值视为一个类别,用组间均方与组内均方之比作为分数,组内均方不足 1e-15 时记 0.0;F_REGRESSION 计算特征与连续目标的相关系数,再换算成 F 值;CHI2 按类别累加特征值,与按类别先验算出的期望值比较,得到卡方统计量。

三种分数都在 fit 阶段一次算出,SelectKBest 按分数降序排列后取前 k 个下标,再按下标升序保存。分数只用于排序,不做显著性判定,也不计算 p 值。

注意

CHI2 要求特征值非负,遇到负值在 fit 阶段抛 IllegalArgumentException。

注意

F_CLASSIF 与 CHI2 把 targets 的每个不同取值当作类别标签;F_REGRESSION 假定 targets 为连续值。

注意

常数特征的分数为 0.0,与目标无关的特征同样得 0.0,排序时按特征下标升序稳定排列。

参见:basalt.ml.SelectKBest, basalt.ml.Estimator

枚举成员

F_CLASSIF()

单因素方差分析 F 值,用于分类标签

F_REGRESSION()

回归 F 值(方差解释比),用于连续标签

CHI2()

卡方统计量,要求非负特征与分类标签

record ShapExplainer.Explanation

一次解释的结果:基准值、SHAP 矩阵、预测与平均绝对值

baseValue 是背景数据集上模型输出的均值;shapValues 为 rows×cols 的矩阵,第 i 行各列之和加 baseValue 等于 predictions[i],这是解释器在各条计算路径上都强制满足的局部有效性。predictions 保存模型在该批样本上的标量输出,分类模型取正类概率或原始得分。

meanAbsShap 是各特征跨样本的绝对 SHAP 均值,长度等于特征数,可直接用于特征重要性排序;它由 shapValues 现算,不含额外信息。

注意

shapValues 是 explain 中新分配的 Matrix,与输入实例不共享存储。

注意

行和与 predictions 的一致性受浮点累加误差影响,比较时需留出容差。

注意

record 不复制数组,构造后修改 predictions 或 meanAbsShap 会改变记录内容。

参见:basalt.ml.ShapExplainer, basalt.core.Matrix

static final class SimpleImputer.Builder

构造 SimpleImputer,设置缺失值策略与常数填充值

默认策略为 MEAN,fillValue 为 0.0;fillValue 只在 CONSTANT 策略下写入统计量,其他策略即使设置也不影响结果。builder() 每次返回新实例,可反复调用 build 得到互相独立的估计器。

策略与填充值都会被序列化:write 依次写策略序数、填充值、特征数与该列的统计量数组,read 按同样顺序还原,因此非法序数或非正特征数会在读取阶段抛 ModelFormatException。

示例
SimpleImputer imputer = SimpleImputer.builder()
        .strategy(SimpleImputer.Strategy.CONSTANT)
        .fillValue(-1.0)
        .build();
imputer.fit(features);
Matrix filled = imputer.transform(features);

注意

构造期不做任何数据检查,缺失值的判定与统计量计算都发生在 fit。

注意

build 不复制 Builder 之外的输入,之后修改 Builder 不会影响已建实例。

参见:basalt.ml.SimpleImputer, basalt.ml.SimpleImputer.Strategy, basalt.ml.StandardScaler.Builder

方法

strategy(Strategy strategy) → Builder

设置填充策略,默认 MEAN

策略只在 fit 阶段影响每列统计量的计算方式;transform 对所有策略一视同仁,把 NaN 位置替换成该列统计量。

参数
  • strategy (Strategy) – 缺失值填充方式,取 MEAN、MEDIAN、MOST_FREQUENT 或 CONSTANT,不允许 null

返回

this,便于链式配置

抛出
  • NullPointerException – strategy 为 null

fillValue(double fillValue) → Builder

设置 CONSTANT 策略使用的填充常数

校验在设置时完成,非法值不会留到 fit。非 CONSTANT 策略下该值仍被保存并写入模型文件,但不参与统计量计算。

参数
  • fillValue (double) – 替换缺失值所用的常数,必须有限(不得为 NaN 或无穷)

返回

this,便于链式配置

抛出
  • IllegalArgumentException – fillValue 为 NaN 或无穷

build() → SimpleImputer

创建配置好的估计器实例

构造器只拷贝策略与填充值,不分配统计数组;统计量在 fit 时按列生成。

注意

未拟合的实例调用 transform 或 statistics 会抛 IllegalStateException。

返回

持有当前策略与填充值的 SimpleImputer,尚未拟合

enum SimpleImputer.Strategy

缺失值填充策略:均值、中位数、众数、常数

MEAN 用该列非缺失值的算术平均;MEDIAN 对非缺失值排序后取中位数,个数为偶数时取中间两个的均值;MOST_FREQUENT 取出现次数最多的值,并列时取数值较小者,因为频次统计基于 TreeMap 的有序遍历。CONSTANT 直接用 fillValue 填充,完全不读取数据。

每列的统计量在 fit 时一次算好并缓存,transform 阶段只做查表替换:NaN 位置写入统计量,有限值原样保留,遇到无穷值则报错。

注意

除 CONSTANT 外,某列全为 NaN 时 fit 抛 IllegalArgumentException,因为没有可用样本。

注意

非缺失位置出现无穷值时 fit 与 transform 都抛 IllegalArgumentException。

注意

策略随模型一起序列化,read 时按序数还原,序数越界由 ModelFormatException 拒绝。

参见:basalt.ml.SimpleImputer, basalt.ml.SimpleImputer.Builder

枚举成员

MEAN()

用该列非缺失值的均值填充

MEDIAN()

用该列非缺失值的中位数填充

MOST_FREQUENT()

用该列出现次数最多的值填充

CONSTANT()

用固定常量填充(缺失指示列另算)

static final class StandardScaler.Builder

构造 StandardScaler,设置是否中心化与是否缩放

withMean 与 withStd 默认都为 true,对应 z = (x - u) / s。两个开关只影响 transform 与 inverseTransform 的步骤,拟合阶段的均值、方差与 scale 始终计算,并被序列化。

两个开关可以任意组合:都关闭时 transform 直接返回输入的副本,只关闭 withStd 时输出为 x - u,只关闭 withMean 时输出为 x / s。

示例
StandardScaler scaler = StandardScaler.builder()
        .withMean(true)
        .withStd(true)
        .build();
scaler.fit(train);
Matrix standardized = scaler.transform(test);
Matrix restored = scaler.inverseTransform(standardized);

注意

拟合使用有偏方差(ddof=0),与 sklearn.preprocessing.StandardScaler 的默认行为一致。

注意

开关值以单字节写入模型文件,read 时按字节非零判断,因此来回读写不会丢失配置。

参见:basalt.ml.StandardScaler, basalt.ml.SimpleImputer.Builder

方法

withMean(boolean withMean) → Builder

设置是否减去列均值

关闭后只做缩放,transform 输出 x / scale,inverseTransform 输出 x * scale。拟合阶段仍会计算均值并写进模型文件,只是变换时不再使用。

参数
  • withMean (boolean) – true 时 transform 减去均值、inverseTransform 加回均值;默认 true

返回

this,便于链式配置

withStd(boolean withStd) → Builder

设置是否除以列标准差

缩放因子是总体标准差(ddof=0)。某列标准差不超过 1e-12 时该列 scale 记为 1.0,避免除零,因此常数特征不会被放大。

参数
  • withStd (boolean) – true 时按标准差缩放,默认 true;与 withMean 互相独立

返回

this,便于链式配置

build() → StandardScaler

创建配置好的标准化器

构造器只保存两个开关,不分配统计数组,也不校验开关组合。

注意

未拟合时调用 transform、inverseTransform 或 mean、scale、variance 会抛 IllegalStateException。

返回

持有当前开关设置的 StandardScaler,尚未拟合

包内可见类型

以下类型没有 public 修饰符,但出现在公开签名中,因此一并列出。它们不是稳定 API,跨版本可能变化。

final class BinnedFeatures

共享的分位分桶特征表示,树模型在桶上做分裂搜索

DecisionTree.fit、RandomForest.fit 与 HistogramGradientBoosting.fit 都先调用 build 把稠密特征离散成 byte 桶号;随机森林随后把同一份结果传给包内的 DecisionTree.fitBinned,避免为每棵树重复分桶与复制矩阵。

每个特征至多 maxBins 个桶,阈值取相邻顺序统计量的中点,判定语义为 value <= threshold 归左。原生内核可用且行数不少于 512、列数不少于 2 时走 NativeKernels.binFeaturesChecked,否则走 Java 排序路径。

build 还会校验 maxBins 落在 [2, 255](MAX_BINS),越界抛 IllegalArgumentException。

注意

中点按 a/2 + b/2 计算,避免两个极大有限值相加溢出;回退分支保证阈值仍严格落在 [a, b) 内。

final class MlChecks

估计器共用的输入校验方法集合

各估计器的 fit 与 predict 入口通过 features、trainingData、predictionData 统一检查空引用、样本数与目标数一致、特征列数与拟合时一致,以及数组内所有取值有限;参数不合法抛 IllegalArgumentException,模型未拟合抛 IllegalStateException。

positiveFinite 与 nonNegativeFinite 供各 Builder 的 build() 校验超参数,因此非法学习率、容差一类问题在构建阶段就暴露,而不是等到训练。

final class PackedTrees

把多棵树拼接成连续数组,供原生集成预测器读取

RandomForest 与 HistogramGradientBoosting 在训练结束以及 read 反序列化后调用 pack,把每棵 TreeModel 的 feature、threshold、left、right、value 平铺进一组数组,offsets 记录第 i 棵树的起始下标。

预测时整组数组一次性传给原生集成内核,避免逐棵树跨 JNI 调用;copyInto 在搬运时把子节点下标加上偏移,因此拼接后的树之间可以互相跳转。

注意

offsets 长度为树数加一,最后一项等于总节点数。

final class TreeModel

扁平的数组式回归/分类树,推理为纯下标游走

节点存放在 feature、threshold、left、right、value 五个平行数组中,feature 为 -1 表示叶节点;predict 从 0 号节点开始按 value <= threshold 选择左右子节点,直到叶节点返回其值,不做对象分发。

DecisionTree、RandomForest、HistogramGradientBoosting 与 IsolationForest 共用这一表示,write 与 read 通过 ModelWriter/ModelReader 落盘,模型文件与内存布局一一对应,读回时校验节点数与子节点范围。

private static final class DecisionTree.Workspace

一次 CART 拟合复用的直方图缓冲区

fitBinned 在完成类别编码后构造一次,随后的递归建树反复在其上累计统计量;按任务类型分支:分类保存每特征每桶的类别计数与左右计数,回归保存和、平方和与样本数。

缓冲区大小由 BinnedFeatures.maxBinCount 与特征数决定,随节点递归传递,避免在每个节点内部重新分配。

Workspace 也持有编码后的类别下标与回归目标数组,使分裂评估只依赖这一个对象。

private static final class HistogramGradientBoosting.HistogramWorkspace

Java 直方图累加的分块暂存区

accumulateHistogramJava 在需要并行时按线程数切块,workspace 保存每个分块的 gradient、hessian、count 数组;clear 只清活动特征对应的桶区间,reduce 把各分块累加到 0 号块,再拷回目标直方图。

实例在 fit 时按特征数、最大桶数与线程数创建,训练结束置空;countAtOrBelow 与 subtractHistogram 也借用它的 maxBins 计算桶偏移。

private record HistogramGradientBoosting.LeafCandidate

best-leaf-first 增长时优先队列中的待分裂叶节点

buildLeafWise 维护一个按 decision.gain 降序的优先队列,每次取出增益最大的候选展开;候选携带该节点的样本下标、深度、分裂决策与已算好的直方图,展开或丢弃时直方图归还池。

深度达到 maxDepth 或样本数不足 2 * minSamplesLeaf 时不再入队,避免无意义的分裂搜索;左右子节点生成后各自重新入队,直到叶数达到 maxLeaves。

private static final class HistogramGradientBoosting.NodeHistogram

单节点的一阶/二阶梯度与样本计数直方图

由三组等长数组组成,下标为 feature * maxBins + bin;rentHistogram 从 histogramPool 借出,建树过程用完即归还,以减少每轮迭代在节点上的分配。

父子节点之间采用 LightGBM 的减法技巧:只累加较小的子节点,较大的子节点由父直方图减去小子节点得到,因此同一份缓冲区会在递归中多次复用。

private record HistogramGradientBoosting.SplitDecision

一次分裂扫描的结果:特征、阈值、桶号与增益

bestSplit 在节点直方图上枚举桶边界并返回增益最大的候选;buildDepthWise 与 buildLeafWise 依据 gain 是否大于 0 判定该节点保持为叶,partition 则用 bin 把样本分到左右两支。

threshold 是写入 TreeModel 供推理比较的实数边界,bin 是训练期分桶下标,两者语义不同,不能互相替代。

private record KMeans.Run

单次 k-means 重启的质心、惯性与迭代轮数

runOnce 用 k-means++ 选取初始质心后迭代到质心位移不超过 tolerance 的平方或达到 maxIterations,返回质心数组、各样本到所属质心平方距离之和(惯性)以及实际完成的轮数。

fit 对 restarts 次运行按惯性取最小者写入模型字段,Run 只作为这一次比较的载体,不对外暴露。

private record KNearestNeighbors.Neighbor

分类 k 近邻的候选:距离与标签

predict 逐行扫描训练集,把 (距离, 标签) 放入按距离降序的小顶堆,堆大小超过 k 即弹出最远者;遍历结束后堆内即为 k 个最近邻,用于多数投票。

投票出现平票时取标签较小者,因此结果对标签的数值顺序有确定依赖。

private record KNeighborsRegressor.Neighbor

回归 k 近邻的候选:距离与目标值

predict 逐行扫描训练集,把 (距离, 目标值) 放入按距离降序的堆并保持至多 k 个元素,最后对堆内 target 求和并除以堆的实际大小。

训练样本少于 k 时堆中只有实际找到的邻居,均值按堆的实际大小计算,而不是按 k。

private record PCA.EigenDecomposition

对称矩阵对角化的特征值与特征向量

jacobi 做循环 Jacobi 对角化后返回该结果:eigenvalues 取收敛矩阵的对角线,eigenvectors 按行存放,第 i 个特征向量是矩阵的第 i 列。

fitCovariance 与 fitGram 都按特征值降序取前 componentCount 个分量;Gram 路径还会用 sqrt(特征值) 归一化特征向量,把样本空间的主成分转回特征空间。

private record SVC.BinarySmoResult

一个二分类子问题的 SMO 解:系数与偏置

fit 对二分类建立一个子问题、对多分类按 one-vs-rest 每类建立一个,每个子问题调用 fitBinarySmo 得到该结果:alpha 长度等于样本数,bias 是决策函数偏置。

写回模型时 alpha 会先乘以标签 y[i] 存入 alphas[m],bias 直接写入 intercepts[m],推理时按同类顺序组合各子问题的输出。