public CategorizationResult Categorize(Recipe recipe) { var result = new CategorizationResult(); this.CategorizeMeal(recipe, result); this.CategorizeDiet(recipe, result); this.CategorizeNutrition(recipe, result); this.CategorizeSkill(recipe, result); this.CategorizeTaste(recipe, result); return(result); }
private void CategorizeSkill(Recipe recipe, CategorizationResult result) { // Common: Has 3 or more ingredients and all ingredients are considered "common" result.SkillCommon = recipe.Ingredients.Length >= 3 && recipe.Ingredients.All(i => this.commonIngredients.ContainsKey(i.Ingredient.Id)); result.Commonality = Convert.ToSingle(result.SkillCommon ? recipe.Ingredients.Average(i => this.commonIngredients[i.Ingredient.Id].Commonality) : 0f); // Easy: Has the word "easy" in the title, or (prep <= 15min and ingredients <= 5) result.SkillEasy = recipe.Title.ToLower().Contains("easy") || (recipe.PrepTime <= 15 && recipe.Ingredients.Length <= 5); // Quick: prep <= 10 and cooktime <= 20 result.SkillQuick = recipe.PrepTime <= 10 && recipe.CookTime <= 20; }
private void CategorizeDiet(Recipe recipe, CategorizationResult result) { var ingredientMeta = recipe.Ingredients.Select(ing => ing.Ingredient.Metadata).ToArray(); var glutenFree = ingredientMeta.All(ing => ing.HasGluten == false); var noAnimals = ingredientMeta.All(ing => ing.HasAnimal == false); var noMeat = ingredientMeta.All(ing => ing.HasMeat == false); var noPork = ingredientMeta.All(ing => ing.HasPork == false); var noRedMeat = ingredientMeta.All(ing => ing.HasRedMeat == false); result.DietGlutenFree = glutenFree; result.DietNoAnimals = noAnimals; result.DietNoMeat = noMeat; result.DietNoPork = noPork; result.DietNoRedMeat = noRedMeat; }
private void CategorizeTaste(Recipe recipe, CategorizationResult result) { var totalMass = new Amount(0, Units.Gram); float totalSweet = 0f, totalSpicy = 0f; foreach (var usage in recipe.Ingredients) { if (usage.Amount == null) { continue; } if (usage.Ingredient.Metadata == null) { continue; } var meta = usage.Ingredient.Metadata; var amt = FormConversion.GetWeightForUsage(usage); if (amt == null) { continue; } totalMass += amt; totalSweet += amt.SizeHigh * meta.Sweet; totalSpicy += amt.SizeHigh * meta.Spicy; } if (totalMass.SizeHigh == 0) { return; // Nothing to calc, exit } var maxRating = totalMass.SizeHigh * 4; var recipeSweet = totalSweet / maxRating; // Pct sweet the recipe is var recipeSpicy = totalSpicy / maxRating; // Pct spicy the recipe is result.TasteSavoryToSweet = Convert.ToByte(recipeSweet * 100); // Scale in terms of percentage result.TasteMildToSpicy = Convert.ToByte(recipeSpicy * 100); }
private static void TestBinaryClassifier() { // Create indexes from twitter using two user supplied terms Console.Write("First Index: "); string firstSearch = Console.ReadLine(); var firsttask = CreateIndex(firstSearch); Console.Write("Second Index: "); string secondSearch = Console.ReadLine(); var secondtask = CreateIndex(secondSearch); Analyzer analyzer = new Analyzer(); // let the user create a sample text entry that we will classify against the two indices Console.Write("Text to Categorize: "); var entryToCategorize = Entry.FromString(Console.ReadLine()); var first = firsttask.Result; var second = secondtask.Result; CategorizationResult result = analyzer.Categorize(entryToCategorize, first, second); Console.Write("And the verdict is ... "); switch (result) { case CategorizationResult.First: Console.WriteLine(firstSearch); break; case CategorizationResult.Undetermined: Console.WriteLine("no clue"); break; case CategorizationResult.Second: Console.WriteLine(secondSearch); break; } first.Save(); second.Save(); }
private void CategorizeMeal(Recipe recipe, CategorizationResult result) { IRecipeClassification trainedRecipe = this.analyzer.GetTrainedRecipe(recipe.Id); if (trainedRecipe != null) { result.MealBreakfast = trainedRecipe.IsBreakfast; result.MealLunch = trainedRecipe.IsLunch; result.MealDinner = trainedRecipe.IsDinner; result.MealDessert = trainedRecipe.IsDessert; } else { var analysis = this.analyzer.GetPrediction(recipe); result.MealBreakfast = analysis.FirstPlace.Equals(Category.Breakfast) || analysis.SecondPlace.Equals(Category.Breakfast); result.MealLunch = analysis.FirstPlace.Equals(Category.Lunch) || analysis.SecondPlace.Equals(Category.Lunch); result.MealDinner = analysis.FirstPlace.Equals(Category.Dinner) || analysis.SecondPlace.Equals(Category.Dinner); result.MealDessert = analysis.FirstPlace.Equals(Category.Dessert) || analysis.SecondPlace.Equals(Category.Dessert); } }
private static void TestClassifier(string input) { Index positiveSentiment = Index.CreateMemoryIndex(); Index negativeSentiment = Index.CreateMemoryIndex(); // train the indexes positiveSentiment.Add(Entry.FromString("this is awesome?")); positiveSentiment.Add(Entry.FromString("i really enjoyed this program")); positiveSentiment.Add(Entry.FromString("the new event was GREAT!")); positiveSentiment.Add(Entry.FromString("I thought that new phone was ideal, some of the key features blew my mind!")); positiveSentiment.Add(Entry.FromString("OK, that's a super idea, lets do it!")); negativeSentiment.Add(Entry.FromString("That was terrible! What were you thinking?")); negativeSentiment.Add(Entry.FromString("OMG! No way! I can't believe that! Terrible!")); negativeSentiment.Add(Entry.FromString("I just got this new phone but wish I hadn't. It's pretty crap!")); negativeSentiment.Add(Entry.FromString("There's no way I'd sign up with them. Their customer service is terrible!")); negativeSentiment.Add(Entry.FromString("That's just rubbish!!!")); Analyzer analyzer = new Analyzer(); Console.WriteLine("Classifying: " + input); CategorizationResult result = analyzer.Categorize(Entry.FromString(input), positiveSentiment, negativeSentiment); switch (result) { case CategorizationResult.First: Console.WriteLine("Positive sentiment"); break; case CategorizationResult.Second: Console.WriteLine("Negative sentiment"); break; case CategorizationResult.Undetermined: Console.WriteLine("Undecided"); break; } }
static void Main(string[] args) { Index spam = Index.CreateMemoryIndex(); Index notspam = Index.CreateMemoryIndex(); // train the indexes HashSet <String> textFirstClass = new HashSet <string>(); textFirstClass.Add("want some viagra?"); textFirstClass.Add("cialis can make you larger"); HashSet <String> textSecondClass = new HashSet <string>(); textSecondClass.Add("Hello, how are you?"); textSecondClass.Add("Did you go to the park today?"); Dictionary <string, Word> allWords = new Dictionary <string, Word>(); int numberDocsFirst = 0; foreach (string text in textFirstClass) { numberDocsFirst++; Entry words = Entry.FromString(text); foreach (string word in words) { if (allWords.ContainsKey(word)) { allWords[word].tfFirst++; allWords[word].docsFirst.Add(numberDocsFirst); } else { Word w = new Word(); w.tfFirst = 1; w.docsFirst.Add(numberDocsFirst); allWords.Add(word, w); } } } int numberDocsSecond = 0; foreach (string text in textSecondClass) { numberDocsSecond++; Entry words = Entry.FromString(text); foreach (string word in words) { if (allWords.ContainsKey(word)) { allWords[word].tfSecond++; allWords[word].docsSecond.Add(numberDocsSecond); } else { Word w = new Word(); w.tfSecond = 1; w.docsSecond.Add(numberDocsSecond); allWords.Add(word, w); } } } foreach (var w in allWords) { w.Value.CalcProbability(numberDocsFirst, numberDocsSecond); spam.Add(w.Key, w.Value.pwFirst); notspam.Add(w.Key, w.Value.pwSecond); } spam.TextCount = numberDocsFirst; notspam.TextCount = numberDocsSecond; Analyzer analyzer = new Analyzer(); CategorizationResult result = analyzer.Categorize( Entry.FromString("cialis viagra"), spam, notspam); switch (result) { case CategorizationResult.First: Console.WriteLine("Spam"); break; case CategorizationResult.Undetermined: Console.WriteLine("Undecided"); break; case CategorizationResult.Second: Console.WriteLine("Not Spam"); break; } Console.ReadKey(); }
private void CategorizeNutrition(Recipe recipe, CategorizationResult result) { float totalGrams = 0; float totalFat = 0; float totalSugar = 0; float totalCal = 0; float totalSodium = 0; float totalCarbs = 0; var noMatch = false; // First, convert every ingredient to weight foreach (var usage in recipe.Ingredients) { // No amount specified for this ingredient if (usage.Amount == null) { noMatch = true; continue; } var meta = usage.Ingredient.Metadata; if (meta == null) { noMatch = true; continue; } var amount = FormConversion.GetWeightForUsage(usage); if (amount == null) { noMatch = true; continue; // Cannot convert this ingredient to grams, skip it } var grams = amount.SizeHigh; totalGrams += grams; if (!(meta.FatPerUnit.HasValue && meta.SugarPerUnit.HasValue && meta.CaloriesPerUnit.HasValue && meta.SodiumPerUnit.HasValue && meta.CarbsPerUnit.HasValue)) { noMatch = true; } else { totalFat += (meta.FatPerUnit.Value * grams) / 100f; // Total fat per 100g totalSugar += (meta.SugarPerUnit.Value * grams) / 100f; // Total sugar per 100g; totalCal += (meta.CaloriesPerUnit.Value * grams) / 100f; // Total Calories per 100g totalSodium += (meta.SodiumPerUnit.Value * grams) / 100f; // Total sodium per 100g totalCarbs += (meta.CarbsPerUnit.Value * grams) / 100f; // Total carbs per 100g } } result.USDAMatch = !noMatch; // Set to true if every ingredient has an exact USDA match // Set totals result.NutritionTotalFat = (short)totalFat; result.NutritionTotalSugar = (short)totalSugar; result.NutritionTotalCalories = (short)totalCal; result.NutritionTotalSodium = (short)totalSodium; result.NutritionTotalCarbs = (short)totalCarbs; // Flag RecipeMetadata depending on totals in recipe if (!noMatch) { result.NutritionLowFat = totalFat <= (totalCal * 0.03); // Definition of Low Fat is 3g of fat per 100 Cal result.NutritionLowSugar = totalSugar <= (totalCal * 0.02); // There is no FDA definition of "Low Sugar" (Can estimate 2g of sugar per 100 Cal or less) result.NutritionLowCalorie = totalCal <= (totalGrams * 1.2); // Definition of Low Calorie is 120 cal per 100g result.NutritionLowSodium = totalSodium <= (totalGrams * 1.4); // Definition of Low Sodium is 140mg per 100g result.NutritionLowCarb = totalCarbs <= (totalCal * 0.05); // No definition for Low Carb, but we can use 5g per 100 Cal or less } }