// Compare Recommendations (Naive Bayes vs. Modified KNN) static void CompareRecommendations() { UserRequest request = new UserRequest(); // input recipe examples string[] first = new string[2] { "apple", "sugar" }; string[] second = new string[4] { "bacon", "chicken", "salt", "black pepper" }; string[] third = new string[4] { "soy sauce", "ginger", "chicken", "water" }; string[] fourth = new string[4] { "mushrooms", "chicken breast", "chicken broth", "sugar" }; string[] fifth = new string[7] { "confectioners sugar", "cocoa powder", "condensed milk", "applesauce", "almond extract", "cheddar cheese", "buttermilk" }; ModelChoice[] modelChoices = new ModelChoice[2] { ModelChoice.NB, ModelChoice.MKNN }; foreach (ModelChoice item in modelChoices) { // recommend ingredients to ADD request.TopRecommendations(10, first, item, true, false); request.TopRecommendations(10, second, item, true, false); request.TopRecommendations(10, third, item, true, false); // recommend ingredients to REMOVE request.TopRecommendations(10, fourth, item, false, true); request.TopRecommendations(10, fifth, item, false, true); } }
// Get Recipes public Data[] GetRecipes(ModelChoice model_choice, DataPurpose data_purpose) { MLContext mlContext = new MLContext(); IDataView testData = GetDataView(model_choice, mlContext, data_purpose); IDataView features = GetDataView(model_choice, mlContext, DataPurpose.FEATURES); return(GetData(testData, features)); }
// Evaluate different models static void Evaluate(ModelChoice choice) { Evaluation eval = new Evaluation(); // Evaluate Non-negative Matrix Factorization (12 minutes) if (choice.Equals(ModelChoice.NMF)) { Recommender nmf = new Recommender(); eval.EvaluateNMF(nmf.GetModel()); } // Evaluate Naive Bayes (5 seconds each) else if (choice.Equals(ModelChoice.NB)) { NaiveBayes nb = new NaiveBayes(); double[][] model = nb.GetModel(); Console.WriteLine("1: Evaluate ALL versions of Naive Bayes"); Console.WriteLine("2: Evaluate only the BEST version of Naive Bayes (normalization, laplace, uniform prior)"); string option = Console.ReadLine(); // ALL if (option == "1") { eval.EvaluateNB(model, false, false, true); eval.EvaluateNB(model, true, false, true); // with laplace smoothing eval.EvaluateNB(model, false, true, true); // with normalization (best results) eval.EvaluateNB(model, true, true, true); // with laplace smoothing and normalization // uniform prior eval.EvaluateNB(model, false, false, false); eval.EvaluateNB(model, true, false, false); // with laplace smoothing eval.EvaluateNB(model, false, true, false); // with normalization (best results) } // BEST eval.EvaluateNB(model, true, true, false); // with laplace smoothing, normalization, and uniform prior } // Evaluate KNN (35 seconds) else if (choice.Equals(ModelChoice.KNN)) { eval.EvaluateKNN(6, DistanceChoice.Jaccard, Voting.Unweighted); } // Evaluate Modified KNN (35 seconds) else { eval.EvaluateModifiedKNN(DistanceChoice.Jaccard_Similarity, Voting.Unweighted); } }
// Get ingredients sorted by what is most recommended public Recommendation[] GetRecommendations(ModelChoice model_choice, int[] recipe) { Recommendation[] recommendations = null; if (model_choice.Equals(ModelChoice.NB)) { NaiveBayes nb = new NaiveBayes(); recommendations = nb.RecipeRecommendations(nb.GetModel(), recipe, true, true, false); } else if (model_choice.Equals(ModelChoice.KNN)) { KNN knn = new KNN(); recommendations = knn.GetRecommendations(6, DistanceChoice.Jaccard, recipe, Voting.Unweighted); } else if (model_choice.Equals(ModelChoice.MKNN)) { KNN knn = new KNN(); int new_k = 0; recommendations = knn.GetRecommendations_ModifiedKNN(recipe, DistanceChoice.Jaccard_Similarity, Voting.Unweighted, ref new_k); } return(recommendations); }
// Get DataView public IDataView GetDataView(ModelChoice choice, MLContext ml, DataPurpose purpose) { // get features if (purpose.Equals(DataPurpose.FEATURES)) { return(LoadFeatures(Path.Combine(Environment.CurrentDirectory, "Data", FEATURES_DATA), ml)); } // get NMF data (entries set aside for testing) else if (choice.Equals(ModelChoice.NMF)) { // test data if (purpose.Equals(DataPurpose.TEST)) { return(LoadData(Path.Combine(Environment.CurrentDirectory, "Data", NMF_TEST_DATA), ml)); } // training data else { return(LoadData(Path.Combine(Environment.CurrentDirectory, "Data", NMF_TRAIN_DATA), ml)); } } // get data (recipes set aside for testing) else { // test data if (purpose.Equals(DataPurpose.TEST)) { return(LoadData(Path.Combine(Environment.CurrentDirectory, "Data", TEST_DATA), ml)); } // training data else { return(LoadData(Path.Combine(Environment.CurrentDirectory, "Data", TRAIN_DATA), ml)); } } }
// Ingredients to ADD to or REMOVE from a recipe public void TopRecommendations(int top, string[] recipe_str, ModelChoice model_choice, bool add, bool include_recipe_ingrs) { DataManager dm = new DataManager(); // get training data Data[] data = dm.GetRecipes(model_choice, DataPurpose.TRAIN); Console.WriteLine("You model choice: " + model_choice.ToString()); // input recipe int[] recipe = new int[recipe_str.Length]; for (int i = 0; i < recipe_str.Length; i++) { try { // trim and make lowercase recipe_str[i] = recipe_str[i].Trim().ToLower(); // find ingredient recipe[i] = data.Where(d => d.ingredient.name.Equals(recipe_str[i])).ToArray()[0].ingredient.id; } catch { // get features (ingredients) string[] features = GetAllIngredients(false); bool found = false; // try finding a similar ingredient foreach (string ingr in features) { if (ingr.StartsWith(recipe_str[i]) || ingr.Contains(recipe_str[i])) { recipe_str[i] = ingr; recipe[i] = data.Where(d => d.ingredient.name.Equals(ingr)).ToArray()[0].ingredient.id; found = true; break; } } // ingredient not found if (found == false) { Console.WriteLine("Ingredient [" + recipe_str[i] + "] was not found"); return; } } } Console.Write("Your recipe: "); PrintRecipe(recipe_str); // keep track of ingredient recommendations Recommendation[] recommendations = null; // Naive Bayes if (model_choice.Equals(ModelChoice.NB)) { NaiveBayes nb = new NaiveBayes(); recommendations = nb.RecipeRecommendations(nb.GetModel(), recipe, true, true, false); } // k Nearest Neighbors else if (model_choice.Equals(ModelChoice.KNN)) { KNN knn = new KNN(); recommendations = knn.GetRecommendations(6, DistanceChoice.Jaccard, recipe, Voting.Unweighted); } // Modified k Nearest Neighbors (dynamic k) else if (model_choice.Equals(ModelChoice.MKNN)) { KNN knn = new KNN(); int new_k = 0; recommendations = knn.GetRecommendations_ModifiedKNN(recipe, DistanceChoice.Jaccard_Similarity, Voting.Unweighted, ref new_k); } else { return; } // Ingredients to Add if (add == true) { Console.WriteLine("Your recommendations:"); for (int i = 0; i < top; i++) { // skip ingredients in recipe if (include_recipe_ingrs == false && recipe_str.Contains(recommendations[i].ingredient.name)) { top++; continue; } Console.WriteLine(recommendations[i].ingredient.name); } } // Ingredients to Remove else { Console.WriteLine("Ingredients ordered by what to remove first:"); // only keep scores of ingredients in input recipe recommendations = recommendations.Where(d => recipe.Contains(d.ingredient.id)).ToArray(); // sort by score recommendations = recommendations.OrderBy(d => d.score).ToArray(); for (int i = 0; i < recipe.Length; i++) { Console.WriteLine(recommendations[i].ingredient.name); } } Console.WriteLine(); }