diff --git a/HISTORY.md b/HISTORY.md index 7a3058d28f..ff3d9093b4 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,9 @@ ### mlpack ?.?.? ###### ????-??-?? + + * The DecisionStump class has been marked deprecated use DecisionTree + class with `NoRecursion=true` or use `ID3DecisionStump` (#2099). + * Added `probabilities_file` parameter to get the probabilities matrix of AdaBoost classifier (#2050). diff --git a/src/mlpack/methods/adaboost/adaboost.hpp b/src/mlpack/methods/adaboost/adaboost.hpp index 509541ba5e..e9179d07fe 100644 --- a/src/mlpack/methods/adaboost/adaboost.hpp +++ b/src/mlpack/methods/adaboost/adaboost.hpp @@ -30,7 +30,7 @@ #include #include -#include +#include namespace mlpack { namespace adaboost { diff --git a/src/mlpack/methods/adaboost/adaboost_main.cpp b/src/mlpack/methods/adaboost/adaboost_main.cpp index 4a3fb4c6f4..2c1aec6dcc 100644 --- a/src/mlpack/methods/adaboost/adaboost_main.cpp +++ b/src/mlpack/methods/adaboost/adaboost_main.cpp @@ -42,7 +42,7 @@ using namespace mlpack; using namespace std; using namespace arma; using namespace mlpack::adaboost; -using namespace mlpack::decision_stump; +using namespace mlpack::tree; using namespace mlpack::perceptron; using namespace mlpack::util; diff --git a/src/mlpack/methods/adaboost/adaboost_model.cpp b/src/mlpack/methods/adaboost/adaboost_model.cpp index ce373a2d75..d62c19f737 100644 --- a/src/mlpack/methods/adaboost/adaboost_model.cpp +++ b/src/mlpack/methods/adaboost/adaboost_model.cpp @@ -16,7 +16,7 @@ using namespace mlpack; using namespace std; using namespace arma; using namespace mlpack::adaboost; -using namespace mlpack::decision_stump; +using namespace mlpack::tree; using namespace mlpack::perceptron; //! Create an empty AdaBoost model. @@ -47,7 +47,7 @@ AdaBoostModel::AdaBoostModel(const AdaBoostModel& other) : mappings(other.mappings), weakLearnerType(other.weakLearnerType), dsBoost(other.dsBoost == NULL ? NULL : - new AdaBoost>(*other.dsBoost)), + new AdaBoost(*other.dsBoost)), pBoost(other.pBoost == NULL ? NULL : new AdaBoost>(*other.pBoost)), dimensionality(other.dimensionality) @@ -77,7 +77,7 @@ AdaBoostModel& AdaBoostModel::operator=(const AdaBoostModel& other) delete dsBoost; dsBoost = (other.dsBoost == NULL) ? NULL : - new AdaBoost>(*other.dsBoost); + new AdaBoost(*other.dsBoost); delete pBoost; pBoost = (other.pBoost == NULL) ? NULL : @@ -105,13 +105,13 @@ void AdaBoostModel::Train(const mat& data, if (weakLearnerType == WeakLearnerTypes::DECISION_STUMP) { delete dsBoost; - - DecisionStump<> ds(data, labels, max(labels) + 1); - dsBoost = new AdaBoost>(data, labels, numClasses, ds, + ID3DecisionStump ds(data, labels, max(labels) + 1); + dsBoost = new AdaBoost(data, labels, numClasses, ds, iterations, tolerance); } else if (weakLearnerType == WeakLearnerTypes::PERCEPTRON) { + delete pBoost; Perceptron<> p(data, labels, max(labels) + 1); pBoost = new AdaBoost>(data, labels, numClasses, p, iterations, tolerance); diff --git a/src/mlpack/methods/adaboost/adaboost_model.hpp b/src/mlpack/methods/adaboost/adaboost_model.hpp index c3e58dcc34..047a02da5c 100644 --- a/src/mlpack/methods/adaboost/adaboost_model.hpp +++ b/src/mlpack/methods/adaboost/adaboost_model.hpp @@ -38,7 +38,7 @@ class AdaBoostModel //! The type of weak learner. size_t weakLearnerType; //! Non-NULL if using decision stumps. - AdaBoost>* dsBoost; + AdaBoost* dsBoost; //! Non-NULL if using perceptrons. AdaBoost>* pBoost; //! Number of dimensions in training data. @@ -79,7 +79,7 @@ class AdaBoostModel //! Modify the dimensionality of the model. size_t& Dimensionality() { return dimensionality; } - //! Train the model. + //! Train the model, treat the data is all of the numeric type. void Train(const arma::mat& data, const arma::Row& labels, const size_t numClasses, diff --git a/src/mlpack/methods/decision_stump/decision_stump.hpp b/src/mlpack/methods/decision_stump/decision_stump.hpp index 416bb2bdbf..7f2b495124 100644 --- a/src/mlpack/methods/decision_stump/decision_stump.hpp +++ b/src/mlpack/methods/decision_stump/decision_stump.hpp @@ -27,6 +27,7 @@ namespace decision_stump { * each bin. Bin i is specified by the range [split[i], split[i + 1]). The * last bin has range up to \infty (split[i + 1] does not exist in that case). * Points that are below the first bin will take the label of the first bin. + * Note: This Class has been and should be removed in mlpack 4.0.0. * * @tparam MatType Type of matrix that is being used (sparse or dense). */ @@ -43,10 +44,10 @@ class DecisionStump * @param numClasses Number of distinct classes in labels. * @param bucketSize Minimum size of bucket when splitting. */ - DecisionStump(const MatType& data, - const arma::Row& labels, - const size_t numClasses, - const size_t bucketSize = 10); + mlpack_deprecated DecisionStump(const MatType& data, + const arma::Row& labels, + const size_t numClasses, + const size_t bucketSize = 10); /** * Alternate constructor which copies the parameters bucketSize and classes @@ -59,11 +60,11 @@ class DecisionStump * @param labels The labels of data. * @param weights Weight vector to use while training. For boosting purposes. */ - DecisionStump(const DecisionStump<>& other, - const MatType& data, - const arma::Row& labels, - const size_t numClasses, - const arma::rowvec& weights); + mlpack_deprecated DecisionStump(const DecisionStump<>& other, + const MatType& data, + const arma::Row& labels, + const size_t numClasses, + const arma::rowvec& weights); /** * Create a decision stump without training. This stump will not be useful @@ -83,10 +84,10 @@ class DecisionStump * @param bucketSize Minimum size of bucket when splitting. * @return The final entropy after splitting. */ - double Train(const MatType& data, - const arma::Row& labels, - const size_t numClasses, - const size_t bucketSize); + mlpack_deprecated double Train(const MatType& data, + const arma::Row& labels, + const size_t numClasses, + const size_t bucketSize); /** * Train the decision stump on the given data, with the given weights. This @@ -100,11 +101,11 @@ class DecisionStump * @param bucketSize Minimum size of bucket when splitting. * @return The final entropy after splitting. */ - double Train(const MatType& data, - const arma::Row& labels, - const arma::rowvec& weights, - const size_t numClasses, - const size_t bucketSize); + mlpack_deprecated double Train(const MatType& data, + const arma::Row& labels, + const arma::rowvec& weights, + const size_t numClasses, + const size_t bucketSize); /** * Classification function. After training, classify test, and put the @@ -114,7 +115,8 @@ class DecisionStump * @param predictedLabels Vector to store the predicted classes after * classifying test data. */ - void Classify(const MatType& test, arma::Row& predictedLabels); + mlpack_deprecated void Classify(const MatType& test, + arma::Row& predictedLabels); //! Access the splitting dimension. size_t SplitDimension() const { return splitDimension; } diff --git a/src/mlpack/methods/decision_stump/decision_stump_main.cpp b/src/mlpack/methods/decision_stump/decision_stump_main.cpp index 6f8f308afc..33417e9481 100644 --- a/src/mlpack/methods/decision_stump/decision_stump_main.cpp +++ b/src/mlpack/methods/decision_stump/decision_stump_main.cpp @@ -125,6 +125,10 @@ static void mlpackMain() ReportIgnoredParam({{ "test", false }}, "predictions"); + Log::Warn << "The Class DecisionStump is deprecated and will be removed in " + << "mlpack 4.0.0. Please use DecisionTree class with maximum_depth " + << "option set to 1 (that will produce a stump)." < #include "gini_gain.hpp" +#include "information_gain.hpp" #include "best_binary_numeric_split.hpp" #include "all_categorical_split.hpp" #include "all_dimension_select.hpp" @@ -124,20 +125,49 @@ class DecisionTree : * @param dimensionSelector Instantiated dimension selection policy. */ template - DecisionTree(MatType data, - const data::DatasetInfo& datasetInfo, - LabelsType labels, - const size_t numClasses, - 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); + DecisionTree( + MatType data, + const data::DatasetInfo& datasetInfo, + LabelsType labels, + const size_t numClasses, + 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); + /** + * Take ownership of another decision tree and train on the given data and + * labels with weights, where the data can be both numeric and categorical. + * 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 other Tree to take ownership of. + * @param data Dataset to train on. + * @param datasetInfo Type information for each dimension of the dataset. + * @param labels Labels for each training point. + * @param numClasses Number of classes in the dataset. + * @param weights The weight list of given label. + * @param minimumLeafSize Minimum number of points in each leaf node. + * @param minimumGainSplit Minimum gain for the node to split. + */ + template + DecisionTree( + const DecisionTree& other, + MatType data, + const data::DatasetInfo& datasetInfo, + LabelsType labels, + const size_t numClasses, + WeightsType weights, + const size_t minimumLeafSize = 10, + const double minimumGainSplit = 1e-7, + const std::enable_if_t::type>::value>* = 0); /** * Construct the decision tree on the given data and labels with weights, * assuming that the data is all of the numeric type. Setting minimumLeafSize @@ -157,19 +187,49 @@ class DecisionTree : * @param dimensionSelector Instantiated dimension selection policy. */ template - DecisionTree(MatType data, - LabelsType labels, - const size_t numClasses, - 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); + DecisionTree( + MatType data, + LabelsType labels, + const size_t numClasses, + 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); + /** + * Take ownership of another decision tree and train on the given data and labels + * with weights, assuming that the data is all of the numeric type. 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 other Tree to take ownership of. + * @param data Dataset to train on. + * @param labels Labels for each training point. + * @param numClasses Number of classes in the dataset. + * @param weights The Weight list of given 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. + */ + template + DecisionTree( + const DecisionTree& other, + MatType data, + LabelsType labels, + const size_t numClasses, + 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); /** * Construct a decision tree without training it. It will be a leaf node with @@ -529,6 +589,16 @@ using DecisionStump = DecisionTree; +/** + * Convenience typedef for ID3decision stumps (single level decision trees + * made with ID3 algorithm). + */ +typedef DecisionTree ID3DecisionStump; } // namespace tree } // namespace mlpack diff --git a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp index 8d08a74d8b..87221e3d7d 100644 --- a/src/mlpack/methods/decision_tree/decision_tree_impl.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree_impl.hpp @@ -12,6 +12,8 @@ #ifndef MLPACK_METHODS_DECISION_TREE_DECISION_TREE_IMPL_HPP #define MLPACK_METHODS_DECISION_TREE_DECISION_TREE_IMPL_HPP +#include "decision_tree.hpp" + namespace mlpack { namespace tree { @@ -116,10 +118,8 @@ DecisionTree::type>::value>*) + const std::enable_if_t::type>::value>*) { using TrueMatType = typename std::decay::type; using TrueLabelsType = typename std::decay::type; @@ -139,6 +139,47 @@ DecisionTree class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + typename ElemType, + bool NoRecursion> +template +DecisionTree::DecisionTree( + const DecisionTree& other, + MatType data, + const data::DatasetInfo& datasetInfo, + LabelsType labels, + const size_t numClasses, + WeightsType weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + const std::enable_if_t::type>::value>*): + NumericAuxiliarySplitInfo(other), + CategoricalAuxiliarySplitInfo(other) +{ + 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)); + + // Pass off work to the weighted Train() method. + Train(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, numClasses, + tmpWeights, minimumLeafSize, minimumGainSplit); +} + //! Construct and train with weights. template class NumericSplitType, @@ -183,6 +224,52 @@ DecisionTree class NumericSplitType, + template class CategoricalSplitType, + typename DimensionSelectionType, + typename ElemType, + bool NoRecursion> +template +DecisionTree::DecisionTree( + const DecisionTree& other, + MatType data, + LabelsType labels, + const size_t numClasses, + WeightsType weights, + const size_t minimumLeafSize, + const double minimumGainSplit, + const size_t maximumDepth, + DimensionSelectionType dimensionSelector, + const std::enable_if_t::type>::value>*): + NumericAuxiliarySplitInfo(other), + CategoricalAuxiliarySplitInfo(other) // other info does need to copy +{ + 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 weighted Train() method. + Train(tmpData, 0, tmpData.n_cols, tmpLabels, numClasses, tmpWeights, + minimumLeafSize, minimumGainSplit, maximumDepth, dimensionSelector); +} + //! Construct, don't train. template class NumericSplitType, @@ -568,7 +655,7 @@ double DecisionTree class NumericSplitType, template class CategoricalSplitType, diff --git a/src/mlpack/tests/adaboost_test.cpp b/src/mlpack/tests/adaboost_test.cpp index ed4d26a1ff..86d74034c4 100644 --- a/src/mlpack/tests/adaboost_test.cpp +++ b/src/mlpack/tests/adaboost_test.cpp @@ -19,7 +19,7 @@ using namespace arma; using namespace mlpack; using namespace mlpack::adaboost; -using namespace mlpack::decision_stump; +using namespace mlpack::tree; using namespace mlpack::perceptron; BOOST_AUTO_TEST_SUITE(AdaBoostTest); @@ -319,13 +319,14 @@ BOOST_AUTO_TEST_CASE(HammingLossIris_DS) // Define your own weak learner, decision stumps in this case. const size_t numClasses = 3; const size_t inpBucketSize = 6; - DecisionStump<> ds(inputData, labels.row(0), numClasses, inpBucketSize); + arma::Row labelsvec = labels.row(0); + ID3DecisionStump ds(inputData, labelsvec, numClasses, inpBucketSize); // Define parameters for AdaBoost. size_t iterations = 50; double tolerance = 1e-10; - AdaBoost> a(tolerance); - double ztProduct = a.Train(inputData, labels.row(0), numClasses, ds, + AdaBoost a(tolerance); + double ztProduct = a.Train(inputData, labelsvec, numClasses, ds, iterations, tolerance); arma::Row predictedLabels; @@ -363,10 +364,11 @@ BOOST_AUTO_TEST_CASE(WeakLearnerErrorIris_DS) // Define your own weak learner, decision stumps in this case. const size_t numClasses = 3; const size_t inpBucketSize = 6; + arma::Row labelsvec = labels.row(0); arma::Row dsPrediction(labels.n_cols); - DecisionStump<> ds(inputData, labels.row(0), numClasses, inpBucketSize); + ID3DecisionStump ds(inputData, labelsvec, numClasses, inpBucketSize); ds.Classify(inputData, dsPrediction); size_t countWeakLearnerError = 0; @@ -379,7 +381,7 @@ BOOST_AUTO_TEST_CASE(WeakLearnerErrorIris_DS) size_t iterations = 50; double tolerance = 1e-10; - AdaBoost> a(inputData, labels.row(0), numClasses, ds, + AdaBoost a(inputData, labelsvec, numClasses, ds, iterations, tolerance); arma::Row predictedLabels; @@ -413,15 +415,16 @@ BOOST_AUTO_TEST_CASE(HammingLossBoundVertebralColumn_DS) // Define your own weak learner, decision stumps in this case. const size_t numClasses = 3; const size_t inpBucketSize = 6; + arma::Row labelsvec = labels.row(0); - DecisionStump<> ds(inputData, labels.row(0), numClasses, inpBucketSize); + ID3DecisionStump ds(inputData, labelsvec, numClasses, inpBucketSize); // Define parameters for AdaBoost. size_t iterations = 50; double tolerance = 1e-10; - AdaBoost> a(tolerance); - double ztProduct = a.Train(inputData, labels.row(0), numClasses, ds, + AdaBoost a(tolerance); + double ztProduct = a.Train(inputData, labelsvec, numClasses, ds, iterations, tolerance); arma::Row predictedLabels; @@ -458,8 +461,9 @@ BOOST_AUTO_TEST_CASE(WeakLearnerErrorVertebralColumn_DS) const size_t numClasses = 3; const size_t inpBucketSize = 6; arma::Row dsPrediction(labels.n_cols); + arma::Row labelsvec = labels.row(0); - DecisionStump<> ds(inputData, labels.row(0), numClasses, inpBucketSize); + ID3DecisionStump ds(inputData, labelsvec, numClasses, inpBucketSize); ds.Classify(inputData, dsPrediction); size_t countWeakLearnerError = 0; @@ -472,7 +476,7 @@ BOOST_AUTO_TEST_CASE(WeakLearnerErrorVertebralColumn_DS) // Define parameters for AdaBoost. size_t iterations = 50; double tolerance = 1e-10; - AdaBoost> a(inputData, labels.row(0), numClasses, ds, + AdaBoost a(inputData, labelsvec, numClasses, ds, iterations, tolerance); arma::Row predictedLabels; @@ -505,15 +509,16 @@ BOOST_AUTO_TEST_CASE(HammingLossBoundNonLinearSepData_DS) // Define your own weak learner, decision stumps in this case. const size_t numClasses = 2; const size_t inpBucketSize = 6; + arma::Row labelsvec = labels.row(0); - DecisionStump<> ds(inputData, labels.row(0), numClasses, inpBucketSize); + ID3DecisionStump ds(inputData, labelsvec, numClasses, inpBucketSize); // Define parameters for Adaboost. size_t iterations = 50; double tolerance = 1e-10; - AdaBoost> a(tolerance); - double ztProduct = a.Train(inputData, labels.row(0), numClasses, ds, + AdaBoost a(tolerance); + double ztProduct = a.Train(inputData, labelsvec, numClasses, ds, iterations, tolerance); arma::Row predictedLabels; @@ -549,10 +554,11 @@ BOOST_AUTO_TEST_CASE(WeakLearnerErrorNonLinearSepData_DS) // Define your own weak learner, decision stumps in this case. const size_t numClasses = 2; const size_t inpBucketSize = 3; + arma::Row labelsvec = labels.row(0); arma::Row dsPrediction(labels.n_cols); - DecisionStump<> ds(inputData, labels.row(0), numClasses, inpBucketSize); + ID3DecisionStump ds(inputData, labelsvec, numClasses, inpBucketSize); ds.Classify(inputData, dsPrediction); size_t countWeakLearnerError = 0; @@ -565,7 +571,7 @@ BOOST_AUTO_TEST_CASE(WeakLearnerErrorNonLinearSepData_DS) size_t iterations = 500; double tolerance = 1e-23; - AdaBoost > a(inputData, labels.row(0), numClasses, ds, + AdaBoost a(inputData, labelsvec, numClasses, ds, iterations, tolerance); arma::Row predictedLabels; @@ -671,6 +677,7 @@ BOOST_AUTO_TEST_CASE(ClassifyTest_NONLINSEP) // Define your own weak learner; in this test decision stumps are used. const size_t numClasses = 2; const size_t inpBucketSize = 3; + arma::Row labelsvec = labels.row(0); arma::mat testData; @@ -684,12 +691,12 @@ BOOST_AUTO_TEST_CASE(ClassifyTest_NONLINSEP) arma::Row dsPrediction(labels.n_cols); - DecisionStump<> ds(inputData, labels.row(0), numClasses, inpBucketSize); + ID3DecisionStump ds(inputData, labelsvec, numClasses, inpBucketSize); // Define parameters for AdaBoost. size_t iterations = 50; double tolerance = 1e-10; - AdaBoost > a(inputData, labels.row(0), numClasses, ds, + AdaBoost a(inputData, labelsvec, numClasses, ds, iterations, tolerance); arma::Row predictedLabels1(testData.n_cols), @@ -907,7 +914,7 @@ BOOST_AUTO_TEST_CASE(PerceptronSerializationTest) } } -BOOST_AUTO_TEST_CASE(DecisionStumpSerializationTest) +BOOST_AUTO_TEST_CASE(ID3DecisionStumpSerializationTest) { // Build an AdaBoost object. mat data = randu(10, 500); @@ -917,8 +924,8 @@ BOOST_AUTO_TEST_CASE(DecisionStumpSerializationTest) for (size_t i = 250; i < 500; ++i) labels[i] = 1; - DecisionStump<> p(data, labels, 2, 800); - AdaBoost> ab(data, labels, 2, p, 50, 1e-10); + ID3DecisionStump p(data, labels, 2, 800); + AdaBoost ab(data, labels, 2, p, 50, 1e-10); // Now create another dataset to train with. mat otherData = randu(5, 200); @@ -930,10 +937,10 @@ BOOST_AUTO_TEST_CASE(DecisionStumpSerializationTest) for (size_t i = 150; i < 200; ++i) otherLabels[i] = 2; - DecisionStump<> p2(otherData, otherLabels, 3, 500); - AdaBoost> abText(otherData, otherLabels, 3, p2, 50, 1e-10); + ID3DecisionStump p2(otherData, otherLabels, 3, 500); + AdaBoost abText(otherData, otherLabels, 3, p2, 50, 1e-10); - AdaBoost> abXml, abBinary; + AdaBoost abXml, abBinary; SerializeObjectAll(ab, abXml, abText, abBinary); @@ -954,16 +961,6 @@ BOOST_AUTO_TEST_CASE(DecisionStumpSerializationTest) abText.WeakLearner(i).SplitDimension()); BOOST_REQUIRE_EQUAL(ab.WeakLearner(i).SplitDimension(), abBinary.WeakLearner(i).SplitDimension()); - - CheckMatrices(ab.WeakLearner(i).Split(), - abXml.WeakLearner(i).Split(), - abText.WeakLearner(i).Split(), - abBinary.WeakLearner(i).Split()); - - CheckMatrices(ab.WeakLearner(i).BinLabels(), - abXml.WeakLearner(i).BinLabels(), - abText.WeakLearner(i).BinLabels(), - abBinary.WeakLearner(i).BinLabels()); } }