diff --git a/src/mlpack/methods/cf/cf_main.cpp b/src/mlpack/methods/cf/cf_main.cpp index 8aba9a8673..add5df5f90 100644 --- a/src/mlpack/methods/cf/cf_main.cpp +++ b/src/mlpack/methods/cf/cf_main.cpp @@ -80,6 +80,18 @@ PROGRAM_INFO("Collaborative Filtering", "This program performs collaborative " " - 'SVDCompleteIncremental' -- SVD complete incremental learning\n" " - 'BiasSVD' -- Bias SVD using a SGD optimizer\n" " - 'SVDPP' -- SVD++ using a SGD optimizer\n" + "\n\n" + "The following neighbor search algorithms can be specified via" + + " the " + PRINT_PARAM_STRING("neighbor_search") + " parameter:" + " - 'Cosine' -- Cosine Search Algorithm\n" + " - 'Euclidean' -- Euclidean Search Algorithm\n" + " - 'Pearson' -- Pearson Search Algorithm\n" + "\n\n" + "The following weight interpolation algorithms can be specified via" + + " the " + PRINT_PARAM_STRING("interpolation") + " parameter:" + " - 'Average' -- Average Interpolation Algorithm\n" + " - 'Regression' -- Regression Interpolation Algorithm\n" + " - 'Similarity' -- Similarity Interpolation Algorithm\n" "\n" "A trained model may be saved to with the " + PRINT_PARAM_STRING("output_model") + " output parameter." @@ -134,19 +146,21 @@ PARAM_INT_IN("recommendations", "Number of recommendations to generate for each" PARAM_INT_IN("seed", "Set the random seed (0 uses std::time(NULL)).", "s", 0); -// Interpolation and Neighbour Search Algorithms +// Interpolation and Neighbor Search Algorithms PARAM_STRING_IN("interpolation", "Algorithm used for weight interpolation.", "i", "Average"); -PARAM_STRING_IN("neighbour_search", "Algorithm used for neighbour search.", +PARAM_STRING_IN("neighbor_search", "Algorithm used for neighbor search.", "f", "Euclidean"); void ComputeRecommendations(CFModel* cf, const size_t numRecs, arma::Mat& recommendations) { - const string ns_algo = CLI::GetParam("neighbour_search"); - const string iw_algo = CLI::GetParam("interpolation"); + // Taking alternatives + const string neighborSearchAlgorithm = CLI::GetParam + ("neighbor_search"); + const string interpolationAlgorithm = CLI::GetParam("interpolation"); // Reading users. if (CLI::HasParam("query")) @@ -157,142 +171,134 @@ void ComputeRecommendations(CFModel* cf, if (users.n_rows > 1) users = users.t(); if (users.n_rows > 1) - Log::Fatal << "List of query users must be one-dimensional!" << std::endl; + Log::Fatal << "List of query users must be one-dimensional!" + << std::endl; - Log::Info << "Generating recommendations for " << users.n_elem << " users." - << endl; + Log::Info << "Generating recommendations for " + << users.n_elem << " users." + << endl; - // Making All the possible paths - if (ns_algo == "Cosine") + // All possible alternatives for Recommendations + if (neighborSearchAlgorithm == "Cosine") { - if (iw_algo == "Average") - { - cf->GetRecommendations(numRecs, recommendations, - users.row(0).t()); - } - else if (iw_algo == "Regression") - { - cf->GetRecommendations(numRecs, recommendations, - users.row(0).t()); - } - else if (iw_algo == "Similarity") - { - cf->GetRecommendations(numRecs, recommendations, - users.row(0).t()); - } + if (interpolationAlgorithm == "Average") + { + cf->GetRecommendations + (numRecs, recommendations, users.row(0).t()); + } + else if (interpolationAlgorithm == "Regression") + { + cf->GetRecommendations + (numRecs, recommendations, users.row(0).t()); + } + else if (interpolationAlgorithm == "Similarity") + { + cf->GetRecommendations + (numRecs, recommendations, users.row(0).t()); + } } - else if (ns_algo == "Euclidean") + else if (neighborSearchAlgorithm == "Euclidean") { - if (iw_algo == "Average") - { - cf->GetRecommendations(numRecs, recommendations, - users.row(0).t()); - } - else if (iw_algo == "Regression") - { - cf->GetRecommendations(numRecs, recommendations, - users.row(0).t()); - } - else if (iw_algo == "Similarity") - { - cf->GetRecommendations(numRecs, recommendations, - users.row(0).t()); - } + if (interpolationAlgorithm == "Average") + { + cf->GetRecommendations + (numRecs, recommendations, users.row(0).t()); + } + else if (interpolationAlgorithm == "Regression") + { + cf->GetRecommendations + (numRecs, recommendations, users.row(0).t()); + } + else if (interpolationAlgorithm == "Similarity") + { + cf->GetRecommendations + (numRecs, recommendations, users.row(0).t()); + } } - else if (ns_algo == "Pearson") + else if (neighborSearchAlgorithm == "Pearson") { - if (iw_algo == "Average") - { - cf->GetRecommendations(numRecs, recommendations, - users.row(0).t()); - } - else if (iw_algo == "Regression") - { - cf->GetRecommendations(numRecs, recommendations, - users.row(0).t()); - } - else if (iw_algo == "Similarity") - { - cf->GetRecommendations(numRecs, recommendations, - users.row(0).t()); - } + if (interpolationAlgorithm == "Average") + { + cf->GetRecommendations + (numRecs, recommendations, users.row(0).t()); + } + else if (interpolationAlgorithm == "Regression") + { + cf->GetRecommendations + (numRecs, recommendations, users.row(0).t()); + } + else if (interpolationAlgorithm == "Similarity") + { + cf->GetRecommendations + (numRecs, recommendations, users.row(0).t()); + } } } else { Log::Info << "Generating recommendations for all users." << endl; - if (ns_algo == "Cosine") + if (neighborSearchAlgorithm == "Cosine") + { + if (interpolationAlgorithm == "Average") { - if (iw_algo == "Average") - { - cf->GetRecommendations(numRecs, recommendations); - } - else if (iw_algo == "Regression") - { - cf->GetRecommendations(numRecs, recommendations); - } - else if (iw_algo == "Similarity") - { - cf->GetRecommendations(numRecs, recommendations); - } + cf->GetRecommendations + (numRecs, recommendations); } - else if (ns_algo == "Euclidean") + else if (interpolationAlgorithm == "Regression") { - if (iw_algo == "Average") - { - cf->GetRecommendations(numRecs, recommendations); - } - else if (iw_algo == "Regression") - { - cf->GetRecommendations(numRecs, recommendations); - } - else if (iw_algo == "Similarity") - { - cf->GetRecommendations(numRecs, recommendations); - } + cf->GetRecommendations + (numRecs, recommendations); } - else if (ns_algo == "Pearson") + else if (interpolationAlgorithm == "Similarity") { - if (iw_algo == "Average") - { - cf->GetRecommendations(numRecs, recommendations); - } - else if (iw_algo == "Regression") - { - cf->GetRecommendations(numRecs, recommendations); - } - else if (iw_algo == "Similarity") - { - cf->GetRecommendations(numRecs, recommendations); - } + cf->GetRecommendations + (numRecs, recommendations); } + } + else if (neighborSearchAlgorithm == "Euclidean") + { + if (interpolationAlgorithm == "Average") + { + cf->GetRecommendations + (numRecs, recommendations); + } + else if (interpolationAlgorithm == "Regression") + { + cf->GetRecommendations + (numRecs, recommendations); + } + else if (interpolationAlgorithm == "Similarity") + { + cf->GetRecommendations + (numRecs, recommendations); + } + } + else if (neighborSearchAlgorithm == "Pearson") + { + if (interpolationAlgorithm == "Average") + { + cf->GetRecommendations + (numRecs, recommendations); + } + else if (interpolationAlgorithm == "Regression") + { + cf->GetRecommendations + (numRecs, recommendations); + } + else if (interpolationAlgorithm == "Similarity") + { + cf->GetRecommendations + (numRecs, recommendations); + } + } } } void ComputeRMSE(CFModel* cf) { - // Interpolation and Neighbour Search - - const string ns_algo = CLI::GetParam("neighbour_search"); - const string iw_algo = CLI::GetParam("interpolation"); + // Interpolation and Neighbor Search + const string neighborSearchAlgorithm = CLI::GetParam("neighbor_search"); + const string interpolationAlgorithm = CLI::GetParam("interpolation"); // Now, compute each test point. arma::mat testData = std::move(CLI::GetParam("test")); @@ -308,59 +314,59 @@ void ComputeRMSE(CFModel* cf) // Now compute the RMSE. arma::vec predictions; - if (ns_algo == "Cosine") + if (neighborSearchAlgorithm == "Cosine") { - if (iw_algo == "Average") - { - cf->Predict(combinations, predictions); - } - else if (iw_algo == "Regression") - { - cf->Predict(combinations, predictions); - } - else if (iw_algo == "Similarity") - { - cf->Predict(combinations, predictions); - } + if (interpolationAlgorithm == "Average") + { + cf->Predict + (combinations, predictions); + } + else if (interpolationAlgorithm == "Regression") + { + cf->Predict + (combinations, predictions); + } + else if (interpolationAlgorithm == "Similarity") + { + cf->Predict + (combinations, predictions); + } } - else if (ns_algo == "Euclidean") + else if (neighborSearchAlgorithm == "Euclidean") { - if (iw_algo == "Average") - { - cf->Predict(combinations, predictions); - } - else if (iw_algo == "Regression") - { - cf->Predict(combinations, predictions); - } - else if (iw_algo == "Similarity") - { - cf->Predict(combinations, predictions); - } + if (interpolationAlgorithm == "Average") + { + cf->Predict + (combinations, predictions); + } + else if (interpolationAlgorithm == "Regression") + { + cf->Predict + (combinations, predictions); + } + else if (interpolationAlgorithm == "Similarity") + { + cf->Predict + (combinations, predictions); + } } - else if (ns_algo == "Pearson") + else if (neighborSearchAlgorithm == "Pearson") { - if (iw_algo == "Average") - { - cf->Predict(combinations, predictions); - } - else if (iw_algo == "Regression") - { - cf->Predict(combinations, predictions); - } - else if (iw_algo == "Similarity") - { - cf->Predict(combinations, predictions); - } + if (interpolationAlgorithm == "Average") + { + cf->Predict + (combinations, predictions); + } + else if (interpolationAlgorithm == "Regression") + { + cf->Predict + (combinations, predictions); + } + else if (interpolationAlgorithm == "Similarity") + { + cf->Predict + (combinations, predictions); + } } // Compute the root of the sum of the squared errors, divide by the number of @@ -482,12 +488,12 @@ static void mlpackMain() "SVDIncompleteIncremental", "SVDCompleteIncremental", "RegSVD", "RandSVD", "BiasSVD", "SVDPP" }, true, "unknown algorithm"); - // Validate the interpolation and neighbour_search policy + // Validate the interpolation and neighbor_search policy RequireParamInSet("interpolation", { "Average", "Regression", "Similarity" }, true, "unknown interpolation algorithm"); - RequireParamInSet("neighbour_search", { "Cosine", - "Euclidean", "Pearson" }, true, "unknown neighbour search algorithm"); + RequireParamInSet("neighbor_search", { "Cosine", + "Euclidean", "Pearson" }, true, "unknown neighbor search algorithm"); ReportIgnoredParam({{ "iteration_only_termination", true }}, "min_residue"); diff --git a/src/mlpack/methods/cf/cf_model.hpp b/src/mlpack/methods/cf/cf_model.hpp index ae568e371d..ef1ebac214 100644 --- a/src/mlpack/methods/cf/cf_model.hpp +++ b/src/mlpack/methods/cf/cf_model.hpp @@ -54,7 +54,7 @@ class GetValueVisitor : public boost::static_visitor * PredictVisitor uses the CFType object to make predictions on the given * combinations of users and items. */ -template class PredictVisitor : public boost::static_visitor { @@ -78,7 +78,7 @@ class PredictVisitor : public boost::static_visitor * RecommendationVisitor uses the CFType object to get recommendations for the * given users. */ -template class RecommendationVisitor : public boost::static_visitor { @@ -146,21 +146,21 @@ class CFModel const bool mit); //! Make predictions. - template void Predict(const arma::Mat& combinations, arma::vec& predictions); //! Compute recommendations for query users. - template void GetRecommendations(const size_t numRecs, arma::Mat& recommendations, const arma::Col& users); //! Compute recommendations for all users. - template + template void GetRecommendations(const size_t numRecs, arma::Mat& recommendations); diff --git a/src/mlpack/methods/cf/cf_model_impl.hpp b/src/mlpack/methods/cf/cf_model_impl.hpp index b503f5f868..aff6beeb11 100644 --- a/src/mlpack/methods/cf/cf_model_impl.hpp +++ b/src/mlpack/methods/cf/cf_model_impl.hpp @@ -34,19 +34,19 @@ void* GetValueVisitor::operator()(CFType* c) const return (void*) c; } -template -PredictVisitor::PredictVisitor( +PredictVisitor::PredictVisitor( const arma::Mat& combinations, arma::vec& predictions) : combinations(combinations), predictions(predictions) { } -template template -void PredictVisitor +void PredictVisitor ::operator()(CFType* c) const { if (!c) @@ -55,13 +55,13 @@ void PredictVisitor return; } - c->template Predicttemplate Predict(combinations, predictions); } -template -RecommendationVisitor +RecommendationVisitor ::RecommendationVisitor( const size_t numRecs, arma::Mat& recommendations, @@ -73,10 +73,10 @@ RecommendationVisitor usersGiven(usersGiven) { } -template +template template -void RecommendationVisitor +void RecommendationVisitor ::operator()(CFType* c) const { if (!c) @@ -86,11 +86,11 @@ void RecommendationVisitor } if (usersGiven) - c->template GetRecommendations(numRecs, recommendations, users); + c->template GetRecommendations + (numRecs, recommendations, users); else - c->template GetRecommendations(numRecs, recommendations); + c->template GetRecommendations + (numRecs, recommendations); } CFModel::~CFModel() @@ -117,37 +117,37 @@ void CFModel::Train(const MatType& data, } //! Make predictions. -template void CFModel::Predict(const arma::Mat& combinations, arma::vec& predictions) { - PredictVisitor predict(combinations, predictions); + PredictVisitor + predict(combinations, predictions); boost::apply_visitor(predict, cf); } //! Compute recommendations for queried users. -template +template void CFModel::GetRecommendations(const size_t numRecs, arma::Mat& recommendations, const arma::Col& users) { - RecommendationVisitor recommendation(numRecs, recommendations, users, true); + RecommendationVisitor + recommendation(numRecs, recommendations, users, true); boost::apply_visitor(recommendation, cf); } //! Compute recommendations for all users. -template +template void CFModel::GetRecommendations(const size_t numRecs, arma::Mat& recommendations) { arma::Col users; - RecommendationVisitor recommendation(numRecs, recommendations, users, false); + RecommendationVisitor + recommendation(numRecs, recommendations, users, false); boost::apply_visitor(recommendation, cf); }