Deterministic classification and regression decision trees for MoonBit
moon add chenzexin02-hash/decision-treeimport {
"chenzexin02-hash/decision-tree" @tree,
}let dataset = @tree.classification_dataset(
[[0.0], [1.0], [2.0], [3.0]],
[0, 0, 1, 1],
2,
).unwrap()
let model = @tree.train_classifier(
dataset,
@tree.ClassificationConfig::default(),
).unwrap()
let label = model.predict([2.5]).unwrap()
let probabilities = model.predict_proba([2.5]).unwrap()let dataset = @tree.regression_dataset(
[[0.0], [1.0], [2.0], [3.0]],
[0.0, 2.0, 4.0, 6.0],
).unwrap()
let model = @tree.train_regressor(
dataset,
@tree.RegressionConfig::default(),
).unwrap()
let prediction = model.predict([2.5]).unwrap()moon run examples/classification
moon run examples/regression
moon run examples/validation
moon run examples/export
moon run examples/weightedmoon clean
moon fmt --check
moon info
moon check --deny-warn
moon build
moon test
moon run examples/classification
moon run examples/regression
moon run examples/validation
moon run examples/export
moon run examples/weighted
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/source-audit.ps1
moon publish --dry-runpub(all) struct ClassificationCandidate {
config : ClassificationConfig
mean_accuracy : Double
} derive(Eq, Debug)pub(all) struct ClassificationConfig {
max_depth : Int
min_samples_split : Int
min_samples_leaf : Int
min_impurity_decrease : Double
criterion : ClassificationCriterion
} derive(Eq, Debug)pub(all) struct ClassificationExplanation {
prediction : Int
probabilities : Array[Double]
confidence : Double
leaf_id : Int
leaf_samples : Int
leaf_impurity : Double
path : Array[DecisionStep]
} derive(Eq, Debug)pub(all) enum ClassificationNode {
ClassificationLeaf(Int, Array[Double], Int, Double)
ClassificationBranch(Int, Double, ClassificationNode, ClassificationNode, Int, Double, Double)
} derive(Eq, Debug)pub(all) struct ClassificationPruningSelection {
best_alpha : Double
best_accuracy : Double
model : ClassificationTree
candidates : Array[ClassificationPruningCandidate]
} derive(Eq, Debug)pub(all) struct ClassificationPruningStep {
alpha : Double
model : ClassificationTree
node_count : Int
leaf_count : Int
} derive(Eq, Debug)pub(all) struct ClassificationReport {
accuracy : Double
macro_precision : Double
macro_recall : Double
macro_f1 : Double
weighted_precision : Double
weighted_recall : Double
weighted_f1 : Double
classes : Array[ClassMetrics]
} derive(Eq, Debug)pub(all) struct ClassificationRule {
leaf_id : Int
conditions : Array[RuleCondition]
prediction : Int
probabilities : Array[Double]
samples : Int
impurity : Double
} derive(Eq, Debug)pub(all) struct ClassificationSelection {
best_config : ClassificationConfig
best_accuracy : Double
candidates : Array[ClassificationCandidate]
} derive(Eq, Debug)pub(all) struct ClassificationTree {
root : ClassificationNode
feature_total : Int
class_total : Int
config : ClassificationConfig
} derive(Eq, Debug)fn ClassificationTree::apply(self : ClassificationTree, features : Array[Double]) -> Result[Int, TreeError]fn ClassificationTree::apply_batch(self : ClassificationTree, rows : Array[Array[Double]]) -> Result[Array[Int], TreeError]fn ClassificationTree::decision_path(self : ClassificationTree, features : Array[Double]) -> Result[Array[DecisionStep], TreeError]fn ClassificationTree::explain(self : ClassificationTree, features : Array[Double]) -> Result[ClassificationExplanation, TreeError]fn ClassificationTree::predict(self : ClassificationTree, features : Array[Double]) -> Result[Int, TreeError]fn ClassificationTree::predict_batch(self : ClassificationTree, rows : Array[Array[Double]]) -> Result[Array[Int], TreeError]fn ClassificationTree::predict_proba(self : ClassificationTree, features : Array[Double]) -> Result[Array[Double], TreeError]fn ClassificationTree::prune(self : ClassificationTree, alpha : Double) -> Result[ClassificationTree, TreeError]fn ClassificationTree::to_dot(self : ClassificationTree, feature_names : Array[String], class_names : Array[String]) -> Result[String, TreeError]fn ClassificationTree::to_json(self : ClassificationTree, feature_names : Array[String], class_names : Array[String]) -> Result[String, TreeError]fn ClassificationTree::to_text(self : ClassificationTree, feature_names : Array[String], class_names : Array[String]) -> Result[String, TreeError]pub(all) struct RegressionCandidate {
config : RegressionConfig
mean_mse : Double
mean_mae : Double
} derive(Eq, Debug)pub(all) struct RegressionExplanation {
prediction : Double
leaf_id : Int
leaf_samples : Int
leaf_variance : Double
path : Array[DecisionStep]
} derive(Eq, Debug)pub(all) enum RegressionNode {
RegressionLeaf(Double, Int, Double)
RegressionBranch(Int, Double, RegressionNode, RegressionNode, Int, Double, Double)
} derive(Eq, Debug)pub(all) struct RegressionPruningSelection {
best_alpha : Double
best_mse : Double
best_mae : Double
model : RegressionTree
candidates : Array[RegressionPruningCandidate]
} derive(Eq, Debug)pub(all) struct RegressionPruningStep {
alpha : Double
model : RegressionTree
node_count : Int
leaf_count : Int
} derive(Eq, Debug)pub(all) struct RegressionRule {
leaf_id : Int
conditions : Array[RuleCondition]
prediction : Double
samples : Int
variance : Double
} derive(Eq, Debug)pub(all) struct RegressionSelection {
best_config : RegressionConfig
best_mse : Double
best_mae : Double
candidates : Array[RegressionCandidate]
} derive(Eq, Debug)pub(all) struct RegressionTree {
root : RegressionNode
feature_total : Int
config : RegressionConfig
} derive(Eq, Debug)fn RegressionTree::apply_batch(self : RegressionTree, rows : Array[Array[Double]]) -> Result[Array[Int], TreeError]fn RegressionTree::decision_path(self : RegressionTree, features : Array[Double]) -> Result[Array[DecisionStep], TreeError]fn RegressionTree::explain(self : RegressionTree, features : Array[Double]) -> Result[RegressionExplanation, TreeError]fn RegressionTree::predict(self : RegressionTree, features : Array[Double]) -> Result[Double, TreeError]fn RegressionTree::predict_batch(self : RegressionTree, rows : Array[Array[Double]]) -> Result[Array[Double], TreeError]fn RegressionTree::prune(self : RegressionTree, alpha : Double) -> Result[RegressionTree, TreeError]fn RegressionTree::to_dot(self : RegressionTree, feature_names : Array[String]) -> Result[String, TreeError]fn RegressionTree::to_json(self : RegressionTree, feature_names : Array[String]) -> Result[String, TreeError]fn RegressionTree::to_text(self : RegressionTree, feature_names : Array[String]) -> Result[String, TreeError]pub(all) enum TreeError {
InvalidMaxDepth(Int)
InvalidMinSamplesSplit(Int)
InvalidMinSamplesLeaf(Int)
InvalidMinImpurityDecrease(Double)
InvalidClassCount(Int)
EmptyDataset
EmptyFeatureRow(Int)
TargetCountMismatch(Int, Int)
InconsistentFeatureCount(Int, Int, Int)
InvalidClassLabel(Int, Int, Int)
NonFiniteFeature(Int, Int)
NonFiniteTarget(Int)
PredictionFeatureCountMismatch(Int, Int)
ModelNotTrained
InvalidFoldCount(Int, Int)
InvalidFeatureNameCount(Int, Int)
InvalidClassNameCount(Int, Int)
InvalidPruningAlpha(Double)
MetricLengthMismatch(Int, Int)
EmptyConfigurationGrid
InvalidTestCount(Int, Int)
ProbabilityRowCountMismatch(Int, Int)
InvalidProbabilityWidth(Int, Int, Int)
InvalidProbabilityValue(Int, Int)
InvalidProbabilitySum(Int)
InvalidFeatureIndex(Int, Int)
WeightCountMismatch(Int, Int)
InvalidSampleWeight(Int)
ZeroTotalWeight
InvalidRepeatCount(Int)
EmptyPruningGrid
} derive(Eq, Debug)pub(all) enum WeightedClassificationNode {
WeightedClassificationLeaf(Int, Array[Double], Int, Double, Double)
WeightedClassificationBranch(Int, Double, WeightedClassificationNode, WeightedClassificationNode, Int, Double, Double, Double)
} derive(Eq, Debug)pub(all) struct WeightedClassificationTree {
root : WeightedClassificationNode
feature_total : Int
class_total : Int
config : ClassificationConfig
} derive(Eq, Debug)fn WeightedClassificationTree::decision_path(self : WeightedClassificationTree, features : Array[Double]) -> Result[Array[DecisionStep], TreeError]fn WeightedClassificationTree::feature_importance(self : WeightedClassificationTree) -> Array[Double]fn WeightedClassificationTree::predict(self : WeightedClassificationTree, features : Array[Double]) -> Result[Int, TreeError]fn WeightedClassificationTree::predict_batch(self : WeightedClassificationTree, rows : Array[Array[Double]]) -> Result[Array[Int], TreeError]fn WeightedClassificationTree::predict_proba(self : WeightedClassificationTree, features : Array[Double]) -> Result[Array[Double], TreeError]pub(all) enum WeightedRegressionNode {
WeightedRegressionLeaf(Double, Int, Double, Double)
WeightedRegressionBranch(Int, Double, WeightedRegressionNode, WeightedRegressionNode, Int, Double, Double, Double)
} derive(Eq, Debug)pub(all) struct WeightedRegressionTree {
root : WeightedRegressionNode
feature_total : Int
config : RegressionConfig
} derive(Eq, Debug)fn WeightedRegressionTree::decision_path(self : WeightedRegressionTree, features : Array[Double]) -> Result[Array[DecisionStep], TreeError]fn WeightedRegressionTree::predict(self : WeightedRegressionTree, features : Array[Double]) -> Result[Double, TreeError]fn WeightedRegressionTree::predict_batch(self : WeightedRegressionTree, rows : Array[Array[Double]]) -> Result[Array[Double], TreeError]fn classification_config_grid(max_depths : Array[Int], min_samples_leaf_values : Array[Int], criteria : Array[ClassificationCriterion]) -> Result[Array[ClassificationConfig], TreeError]fn classification_dataset(rows : Array[Array[Double]], labels : Array[Int], class_count : Int) -> Result[ClassificationDataset, TreeError]fn classification_report(actual : Array[Int], predicted : Array[Int], class_count : Int) -> Result[ClassificationReport, TreeError]fn classifier_partial_dependence(model : ClassificationTree, dataset : ClassificationDataset, feature_index : Int, values : Array[Double]) -> Result[ClassificationPartialDependence, TreeError]fn classifier_permutation_importance(model : ClassificationTree, dataset : ClassificationDataset, seed : Int) -> Result[Array[Double], TreeError]fn cross_validate_classifier(dataset : ClassificationDataset, config : ClassificationConfig, fold_count : Int, seed : Int) -> Result[ClassificationValidation, TreeError]fn cross_validate_regressor(dataset : RegressionDataset, config : RegressionConfig, fold_count : Int, seed : Int) -> Result[RegressionValidation, TreeError]fn regression_config_grid(max_depths : Array[Int], min_samples_leaf_values : Array[Int]) -> Result[Array[RegressionConfig], TreeError]fn regression_dataset(rows : Array[Array[Double]], targets : Array[Double]) -> Result[RegressionDataset, TreeError]fn regression_report(actual : Array[Double], predicted : Array[Double]) -> Result[RegressionReport, TreeError]fn regressor_partial_dependence(model : RegressionTree, dataset : RegressionDataset, feature_index : Int, values : Array[Double]) -> Result[RegressionPartialDependence, TreeError]fn regressor_permutation_importance(model : RegressionTree, dataset : RegressionDataset, seed : Int) -> Result[Array[Double], TreeError]fn repeated_cross_validate_classifier(dataset : ClassificationDataset, config : ClassificationConfig, fold_count : Int, repeat_count : Int, seed : Int) -> Result[RepeatedClassificationValidation, TreeError]fn repeated_cross_validate_regressor(dataset : RegressionDataset, config : RegressionConfig, fold_count : Int, repeat_count : Int, seed : Int) -> Result[RepeatedRegressionValidation, TreeError]fn select_classifier(dataset : ClassificationDataset, configs : Array[ClassificationConfig], fold_count : Int, seed : Int) -> Result[ClassificationSelection, TreeError]fn select_classifier_pruning_alpha(dataset : ClassificationDataset, config : ClassificationConfig, alphas : Array[Double], fold_count : Int, seed : Int) -> Result[ClassificationPruningSelection, TreeError]fn select_regressor(dataset : RegressionDataset, configs : Array[RegressionConfig], fold_count : Int, seed : Int) -> Result[RegressionSelection, TreeError]fn select_regressor_pruning_alpha(dataset : RegressionDataset, config : RegressionConfig, alphas : Array[Double], fold_count : Int, seed : Int) -> Result[RegressionPruningSelection, TreeError]fn train_classifier(dataset : ClassificationDataset, config : ClassificationConfig) -> Result[ClassificationTree, TreeError]fn train_regressor(dataset : RegressionDataset, config : RegressionConfig) -> Result[RegressionTree, TreeError]fn train_weighted_classifier(dataset : WeightedClassificationDataset, config : ClassificationConfig) -> Result[WeightedClassificationTree, TreeError]fn train_weighted_regressor(dataset : WeightedRegressionDataset, config : RegressionConfig) -> Result[WeightedRegressionTree, TreeError]Deterministic classification and regression decision trees for MoonBit