예제 #1
0
        // Get Modified KNN Recommendations
        public Recommendation[] GetRecommendations_ModifiedKNN(int[] current_recipe, DistanceChoice distance_choice, Voting voting, ref int new_k)
        {
            MLContext   ml    = new MLContext();
            DataManager dm    = new DataManager();
            int         max_k = dm.GetRecipes(ModelChoice.KNN, DataPurpose.TEST).GroupBy(d => d.recipeId).ToArray().Length;

            Data[]   train_data = dm.GetRecipes(ModelChoice.KNN, DataPurpose.TRAIN);
            string[] ingrNames  = dm.GetFeatures();

            // keep track of ingredient scores (recommendations)
            Recommendation[] recommendations = new Recommendation[ingrNames.Length];
            for (int i = 0; i < ingrNames.Length; i++)
            {
                recommendations[i] = new Recommendation(new Ingredient(i, ingrNames[i]), 0.0);
            }

            // calculate all distances, find nearest neighbors to current recipe
            Neighbors[] distances = GetDistances(distance_choice, current_recipe, train_data, voting);

            recommendations = ModifiedKNN(recommendations, distances, current_recipe, ingrNames, ref new_k, max_k);

            // sort
            recommendations = recommendations.OrderByDescending(d => d.score).ToArray();

            return(recommendations);
        }
예제 #2
0
        // Get recommendations
        public Recommendation[] GetRecommendations(int k, DistanceChoice distance_choice, int[] recipe, Voting voting)
        {
            MLContext   ml = new MLContext();
            DataManager dm = new DataManager();

            // get features (ingredient names)
            string[] ingrNames = dm.GetFeatures();
            // get training recipes
            Data[] data = dm.GetRecipes(ModelChoice.KNN, DataPurpose.TRAIN);

            Recommendation[] recommendations = new Recommendation[ingrNames.Length];
            // iterate through all ingredients
            for (int i = 0; i < ingrNames.Length; i++)
            {
                Ingredient current_ingr = new Ingredient(i, ingrNames[i]);
                // calculate all distances
                Neighbors[] distances = GetDistances(distance_choice, recipe, data, voting);

                double recommended     = 0;
                double not_recommended = 0;

                // k nearest neighbors vote
                // recommend ingredient if the majority of neighbors contains the ingredient
                for (int top = 0; top < k; top++)
                {
                    // recommend ingredient
                    if (distances[top].recipe.Contains(i))
                    {
                        if (voting.Equals(Voting.Unweighted))
                        {
                            recommended++;
                        }
                        else
                        {
                            recommended += distances[top].distance;
                        }
                    }
                    // do not recommend ingredient
                    else
                    {
                        if (voting.Equals(Voting.Unweighted))
                        {
                            not_recommended++;
                        }
                        else
                        {
                            not_recommended += distances[top].distance;
                        }
                    }
                }
                recommendations[i] = new Recommendation(current_ingr, (recommended + 1.0) / (not_recommended + 2.0));
            }
            recommendations = recommendations.OrderByDescending(r => r.score).ToArray();
            return(recommendations);
        }
        // Get recommendations for a recipe
        // the ingredient score is equivalent to the posterior
        public Recommendation[] RecipeRecommendations(double[][] model, int[] recipe, bool laplace, bool normalize, bool prior)
        {
            MLContext   ml = new MLContext();
            DataManager dm = new DataManager();

            // get features (unique ingredients)
            string[] ingr_names = dm.GetFeatures();

            // get number of training recipes
            IDataView allrecipes  = dm.GetDataView(ModelChoice.NB, ml, DataPurpose.TRAIN);
            int       num_recipes = allrecipes.GetColumn <int>(allrecipes.Schema["recipeId"]).ToArray().Length;

            Recommendation[] recommendations = new Recommendation[ingr_names.Length];

            // iterate through all features (unique ingredients)
            for (int f = 0; f < ingr_names.Length; f++)
            {
                double likelihood = 1.0;
                // iterate through all the ingredients in the recipe
                foreach (int i in recipe)
                {
                    // ignore matching ingredients
                    if (i != f)
                    {
                        // laplace smoothing
                        if (laplace == true)
                        {
                            likelihood *= (model[i][f] + 1.0) / (model[f][f] + ingr_names.Length);
                        }
                        else
                        {
                            likelihood *= model[i][f] / model[f][f];
                        }

                        // normalize
                        if (normalize == true)
                        {
                            likelihood /= model[i][i];
                        }
                    }
                }
                // prior
                if (prior == true)
                {
                    likelihood *= model[f][f] / num_recipes;
                }
                recommendations[f] = new Recommendation(new Ingredient(f, ingr_names[f]), likelihood);
            }
            // sort
            recommendations = recommendations.OrderByDescending(t => t.score).ToArray();

            return(recommendations);
        }
예제 #4
0
        // Evaluate Non-negative Matrix Factorization
        public void EvaluateNMF(ITransformer model)
        {
            Console.WriteLine("\nEvaluating NMF...");
            MLContext mlContext = new MLContext();

            // get test data
            DataManager dm = new DataManager();
            // test data
            IDataView testData = dm.GetDataView(ModelChoice.NMF, mlContext, DataPurpose.TEST);

            Data[] test_data = dm.GetRecipes(ModelChoice.NMF, DataPurpose.TEST);
            // train data
            IDataView trainData = dm.GetDataView(ModelChoice.NMF, mlContext, DataPurpose.TRAIN);

            Data[] train_data = dm.GetRecipes(ModelChoice.NMF, DataPurpose.TRAIN);

            // features
            string[] features    = dm.GetFeatures();
            int[]    recipeArray = testData.GetColumn <int>(testData.Schema["recipeId"]).ToArray();

            Results     results     = new Results(0);
            Recommender recommender = new Recommender();

            // distinct test recipes
            int[] distinct_recipes = recipeArray.Distinct().ToArray();

            // for each test recipe
            foreach (int r in distinct_recipes)
            {
                Recommendation[] recommendations = new Recommendation[features.Length];
                Data[]           recipe          = test_data.Where(d => d.recipeId == r && d.score == 1).ToArray();
                Data[]           trecipe         = train_data.Where(d => d.recipeId == r && d.score == 1).ToArray();
                // get recipe r
                Data[] combined       = recipe.Concat(trecipe).ToArray();
                int[]  current_recipe = dm.GetRecipe(combined.ToArray());

                // iterate through all features
                for (int i = 0; i < dm.GetFeatures().Length; i++)
                {
                    // make prediction (get score)
                    double prediction = recommender.SinglePrediction(mlContext, model, i, r);
                    // save score of ingredient
                    recommendations[i] = new Recommendation(new Ingredient(i, features[i]), prediction);
                }
                // sort
                recommendations = recommendations.OrderByDescending(d => d.score).ToArray();
                results         = GetResults(results, recommendations, current_recipe);
            }
            // Display accuracy results
            results.ShowResults();
            Console.WriteLine();
        }