From a2c9cd0c2d177e0150b7830b8514972efcb6ef0d Mon Sep 17 00:00:00 2001 From: Rishabh Garg <56191449+RishabhGarg108@users.noreply.github.com> Date: Fri, 9 Apr 2021 15:52:37 +0530 Subject: [PATCH] Added Train overloads --- .../decision_tree/decision_tree_regressor.hpp | 116 ++++++++++++ .../decision_tree_regressor_impl.hpp | 170 ++++++++++++++++++ 2 files changed, 286 insertions(+) diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp index 8911e8c79f..17358d07a6 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor.hpp @@ -257,6 +257,122 @@ class DecisionTreeRegressor : * Clean up memory. */ ~DecisionTreeRegressor(); + + /** + * Train the decision tree on the given data. This will overwrite the + * existing model. The data may have numeric and categorical types, specified + * by the datasetInfo parameter. Setting minimumLeafSize and + * minimumGainSplit too small may cause the tree to overfit, but setting them + * too large may cause it to underfit. + * + * Use std::move if data or labels are no longer needed to avoid copies. + * + * @param data Dataset to train on. + * @param datasetInfo Type information for each dimension. + * @param labels Labels for each training point. + * @param minimumLeafSize Minimum number of points in each leaf node. + * @param minimumGainSplit Minimum gain for the node to split. + * @param maximumDepth Maximum depth for the tree. + * @param dimensionSelector Instantiated dimension selection policy. + * @return The final entropy of decision tree. + */ + template + double Train(MatType data, + const data::DatasetInfo& datasetInfo, + LabelsType labels, + const size_t minimumLeafSize = 10, + const double minimumGainSplit = 1e-7, + const size_t maximumDepth = 0, + DimensionSelectionType dimensionSelector = + DimensionSelectionType()); + + /** + * Train the decision tree on the given data, assuming that all dimensions are + * numeric. This will overwrite the given model. Setting minimumLeafSize and + * minimumGainSplit too small may cause the tree to overfit, but setting them + * too large may cause it to underfit. + * + * Use std::move if data or labels are no longer needed to avoid copies. + * + * @param data Dataset to train on. + * @param labels Labels for each training point. + * @param minimumLeafSize Minimum number of points in each leaf node. + * @param minimumGainSplit Minimum gain for the node to split. + * @param maximumDepth Maximum depth for the tree. + * @param dimensionSelector Instantiated dimension selection policy. + * @return The final entropy of decision tree. + */ + template + double Train(MatType data, + LabelsType labels, + const size_t minimumLeafSize = 10, + const double minimumGainSplit = 1e-7, + const size_t maximumDepth = 0, + DimensionSelectionType dimensionSelector = + DimensionSelectionType()); + + /** + * Train the decision tree on the given weighted data. This will overwrite + * the existing model. The data may have numeric and categorical types, + * specified by the datasetInfo parameter. Setting minimumLeafSize and + * minimumGainSplit too small may cause the tree to overfit, but setting them + * too large may cause it to underfit. + * + * Use std::move if data, labels or weights are no longer needed to avoid + * copies. + * + * @param data Dataset to train on. + * @param datasetInfo Type information for each dimension. + * @param labels Labels for each training point. + * @param weights Weights of all the labels + * @param minimumLeafSize Minimum number of points in each leaf node. + * @param minimumGainSplit Minimum gain for the node to split. + * @param maximumDepth Maximum depth for the tree. + * @param dimensionSelector Instantiated dimension selection policy. + * @return The final entropy of decision tree. + */ + template + double Train(MatType data, + const data::DatasetInfo& datasetInfo, + LabelsType labels, + WeightsType weights, + const size_t minimumLeafSize = 10, + const double minimumGainSplit = 1e-7, + const size_t maximumDepth = 0, + DimensionSelectionType dimensionSelector = + DimensionSelectionType(), + const std::enable_if_t::type>::value>* = 0); + + /** + * Train the decision tree on the given weighted data, assuming that all + * dimensions are numeric. This will overwrite the given model. Setting + * minimumLeafSize and minimumGainSplit too small may cause the tree to + * overfit, but setting them too large may cause it to underfit. + * + * Use std::move if data, labels or weights are no longer needed to avoid + * copies. + * + * @param data Dataset to train on. + * @param labels Labels for each training point. + * @param weights Weights of all the labels + * @param minimumLeafSize Minimum number of points in each leaf node. + * @param minimumGainSplit Minimum gain for the node to split. + * @param maximumDepth Maximum depth for the tree. + * @param dimensionSelector Instantiated dimension selection policy. + * @return The final entropy of decision tree. + */ + template + double Train(MatType data, + LabelsType labels, + WeightsType weights, + const size_t minimumLeafSize = 10, + const double minimumGainSplit = 1e-7, + const size_t maximumDepth = 0, + DimensionSelectionType dimensionSelector = + DimensionSelectionType(), + const std::enable_if_t::type>::value>* = 0); }; diff --git a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp index 9ba0623341..1145b110e0 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_regressor_impl.hpp @@ -420,6 +420,176 @@ DecisionTreeRegressor class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +double DecisionTreeRegressor::Train( + MatType data, + const data::DatasetInfo& datasetInfo, + LabelsType labels, + const size_t minimumLeafSize, + const double minimumGainSplit, + const size_t maximumDepth, + DimensionSelectionType dimensionSelector) +{ + // Sanity check on data. + util::CheckSameSizes(data, labels, "DecisionTreeRegressor::Train()"); + + using TrueMatType = typename std::decay::type; + using TrueLabelsType = typename std::decay::type; + + // Copy or move data. + TrueMatType tmpData(std::move(data)); + TrueLabelsType tmpLabels(std::move(labels)); + + // Set the correct dimensionality for the dimension selector. + dimensionSelector.Dimensions() = tmpData.n_rows; + + // Pass off work to the Train() method. + arma::rowvec weights; // Fake weights, not used. + return Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, + numClasses, weights, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); +} + +//! Train on the given data, assuming all dimensions are numeric. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +double DecisionTreeRegressor::Train( + MatType data, + LabelsType labels, + const size_t minimumLeafSize, + const double minimumGainSplit, + const size_t maximumDepth, + DimensionSelectionType dimensionSelector) +{ + // Sanity check on data. + util::CheckSameSizes(data, labels, "DecisionTreeRegressor::Train()"); + + using TrueMatType = typename std::decay::type; + using TrueLabelsType = typename std::decay::type; + + // Copy or move data. + TrueMatType tmpData(std::move(data)); + TrueLabelsType tmpLabels(std::move(labels)); + + // Set the correct dimensionality for the dimension selector. + dimensionSelector.Dimensions() = tmpData.n_rows; + + // Pass off work to the Train() method. + arma::rowvec weights; // Fake weights, not used. + return Train(tmpData, 0, tmpData.n_cols, tmpLabels, numClasses, + weights, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); +} + +//! Train on the given weighted data. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +double DecisionTreeRegressor::Train( + MatType data, + const data::DatasetInfo& datasetInfo, + LabelsType labels, + WeightsType weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + const size_t maximumDepth, + DimensionSelectionType dimensionSelector, + const std::enable_if_t< + arma::is_arma_type< + typename std::remove_reference< + WeightsType>::type>::value>*) +{ + // Sanity check on data. + util::CheckSameSizes(data, labels, "DecisionTreeRegressor::Train()"); + + using TrueMatType = typename std::decay::type; + using TrueLabelsType = typename std::decay::type; + using TrueWeightsType = typename std::decay::type; + + // Copy or move data. + TrueMatType tmpData(std::move(data)); + TrueLabelsType tmpLabels(std::move(labels)); + TrueWeightsType tmpWeights(std::move(weights)); + + // Set the correct dimensionality for the dimension selector. + dimensionSelector.Dimensions() = tmpData.n_rows; + + // Pass off work to the Train() method. + return Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, + numClasses, tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); +} + +//! Train on the given weighted all numeric data. +template class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + bool NoRecursion> +template +double DecisionTreeRegressor::Train( + MatType data, + LabelsType labels, + WeightsType weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + const size_t maximumDepth, + DimensionSelectionType dimensionSelector, + const std::enable_if_t< + arma::is_arma_type< + typename std::remove_reference< + WeightsType>::type>::value>*) +{ + // Sanity check on data. + util::CheckSameSizes(data, labels, "DecisionTreeRegressor::Train()"); + + using TrueMatType = typename std::decay::type; + using TrueLabelsType = typename std::decay::type; + using TrueWeightsType = typename std::decay::type; + + // Copy or move data. + TrueMatType tmpData(std::move(data)); + TrueLabelsType tmpLabels(std::move(labels)); + TrueWeightsType tmpWeights(std::move(weights)); + + // Set the correct dimensionality for the dimension selector. + dimensionSelector.Dimensions() = tmpData.n_rows; + + // Pass off work to the Train() method. + return Train(tmpData, 0, tmpData.n_cols, tmpLabels, numClasses, + tmpWeights, minimumLeafSize, minimumGainSplit, maximumDepth, + dimensionSelector); +} + } // namespace tree } // namespace mlpack