diff --git a/src/mlpack/core/util/size_checks.hpp b/src/mlpack/core/util/size_checks.hpp index c2d60459b8..f5125a591b 100644 --- a/src/mlpack/core/util/size_checks.hpp +++ b/src/mlpack/core/util/size_checks.hpp @@ -26,18 +26,27 @@ namespace util { * error generation. * @param addInfo Name to use for labels for precise error generation. Default * is "labels"; for example, "weights" could also be used. + * @param isDataTranspose Bool parameter which can be set true to transpose data + * before size-check. Default is false. + * @param isLabelTranspose Bool parameter which can be set true to transpose label + * before size-check. Default is false. */ template inline void CheckSameSizes(const DataType& data, const LabelsType& label, const std::string& callerDescription, - const std::string& addInfo = "labels") -{ - if (data.n_cols != label.n_cols) + const std::string& addInfo = "labels", + const bool& isDataTranspose = false, + const bool& isLabelTranspose = false) +{ + const size_t dataPoints = (isDataTranspose == true) ? data.n_rows : data.n_cols; + const size_t labelPoints = (isLabelTranspose == true) ? label.n_rows : label.n_cols; + + if (dataPoints != labelPoints) { std::ostringstream oss; - oss << callerDescription << ": number of points (" << data.n_cols << ") " - << "does not match number of " << addInfo << " (" << label.n_cols + oss << callerDescription << ": number of points (" << dataPoints << ") " + << "does not match number of " << addInfo << " (" << labelPoints << ")!" << std::endl; throw std::invalid_argument(oss.str()); } diff --git a/src/mlpack/methods/kmeans/kmeans_impl.hpp b/src/mlpack/methods/kmeans/kmeans_impl.hpp index 4195da81ac..e8f782e916 100644 --- a/src/mlpack/methods/kmeans/kmeans_impl.hpp +++ b/src/mlpack/methods/kmeans/kmeans_impl.hpp @@ -14,6 +14,7 @@ #include #include +#include namespace mlpack { namespace kmeans { @@ -161,15 +162,8 @@ Cluster(const MatType& data, // Check validity of initial guess. if (initialGuess) { - if (centroids.n_cols != clusters) - Log::Fatal << "KMeans::Cluster(): wrong number of initial cluster " - << "centroids (" << centroids.n_cols << ", should be " << clusters - << ")!" << std::endl; - - if (centroids.n_rows != data.n_rows) - Log::Fatal << "KMeans::Cluster(): initial cluster centroids have wrong " - << " dimensionality (" << centroids.n_rows << ", should be " - << data.n_rows << ")!" << std::endl; + util::CheckSameSizes(centroids, clusters, "KMeans::Cluster()", "clusters"); + util::CheckSameDimensionality(data, centroids, "KMeans::Cluster()"); } // Use the partitioner to come up with the partition assignments and calculate @@ -288,10 +282,7 @@ Cluster(const MatType& data, // Now, the initial assignments. First determine if they are necessary. if (initialAssignmentGuess) { - if (assignments.n_elem != data.n_cols) - Log::Fatal << "KMeans::Cluster(): initial cluster assignments (length " - << assignments.n_elem << ") not the same size as the dataset (size " - << data.n_cols << ")!" << std::endl; + util::CheckSameSizes(data, assignments, "KMeans::Cluster()", "assignments"); // Calculate initial centroids. arma::Row counts; diff --git a/src/mlpack/methods/linear_regression/linear_regression.cpp b/src/mlpack/methods/linear_regression/linear_regression.cpp index d3d4a2cd3f..774425ebc7 100644 --- a/src/mlpack/methods/linear_regression/linear_regression.cpp +++ b/src/mlpack/methods/linear_regression/linear_regression.cpp @@ -12,6 +12,7 @@ */ #include "linear_regression.hpp" #include +#include using namespace mlpack; using namespace mlpack::regression; @@ -57,6 +58,10 @@ double LinearRegression::Train(const arma::mat& predictors, // We store the number of rows and columns of the predictors. // Reminder: Armadillo stores the data transposed from how we think of it, // that is, columns are actually rows (see: column major order). + + // Sanity check on data. + util::CheckSameSizes(predictors, responses, "LinearRegression::Train()"); + const size_t nCols = predictors.n_cols; arma::mat p = predictors; @@ -95,7 +100,11 @@ void LinearRegression::Predict(const arma::mat& points, { // We want to be sure we have the correct number of dimensions in the // dataset. - Log::Assert(points.n_rows == parameters.n_rows - 1); + // Prevent underflow. + const size_t labels = (parameters.n_rows == 0) ? size_t(0) : + size_t(parameters.n_rows - 1); + util::CheckSameDimensionality(points, labels, "LinearRegression::Predict()", + "points"); // Get the predictions, but this ignores the intercept value // (parameters[0]). predictions = arma::trans(parameters.subvec(1, parameters.n_elem - 1)) @@ -107,7 +116,8 @@ void LinearRegression::Predict(const arma::mat& points, { // We want to be sure we have the correct number of dimensions in // the dataset. - Log::Assert(points.n_rows == parameters.n_rows); + util::CheckSameDimensionality(points, parameters, + "LinearRegression::Predict()", "points"); predictions = arma::trans(parameters) * points; } } @@ -115,6 +125,9 @@ void LinearRegression::Predict(const arma::mat& points, double LinearRegression::ComputeError(const arma::mat& predictors, const arma::rowvec& responses) const { + // Sanity check on data. + util::CheckSameSizes(predictors, responses, "LinearRegression::Train()"); + // Get the number of columns and rows of the dataset. const size_t nCols = predictors.n_cols; const size_t nRows = predictors.n_rows; diff --git a/src/mlpack/methods/matrix_completion/matrix_completion.cpp b/src/mlpack/methods/matrix_completion/matrix_completion.cpp index 6210b69453..0101760525 100644 --- a/src/mlpack/methods/matrix_completion/matrix_completion.cpp +++ b/src/mlpack/methods/matrix_completion/matrix_completion.cpp @@ -11,6 +11,7 @@ */ #include "matrix_completion.hpp" +#include namespace mlpack { namespace matrix_completion { @@ -59,13 +60,8 @@ void MatrixCompletion::CheckValues() << "indices does not have 2 rows!" << std::endl; } - if (indices.n_cols != values.n_elem) - { - Log::Fatal << "MatrixCompletion::CheckValues(): the number of constraint " - << "indices (columns of constraint indices matrix) does not match the " - << "number of constraint values (length of constraint value vector)!" - << std::endl; - } + util::CheckSameSizes(indices, values, + "MatrixCompletion::CheckValues()", "labels", false, true); for (size_t i = 0; i < values.n_elem; ++i) {