private void AddRecommender <TUserRatings>(int userId, TUserRatings ratings, IUserInputClassifier <TUserRatings> recommenderRatingClassifier) where TUserRatings : IInputForUserWithItemIds { ClassifiedUserInput <TUserRatings> classifiedRatings = recommenderRatingClassifier.Classify(ratings); List <int> recs = new List <int>(classifiedRatings.Liked.ItemIds); Recommender recommender = new Recommender(userId, recs); Recommenders.Add(recommender); }
public IBasicTrainingData <IPositiveFeedbackForUser> AsPositiveFeedback(IUserInputClassifier <MalUserListEntries> classifier) { Dictionary <int, IPositiveFeedbackForUser> basicUsers = new Dictionary <int, IPositiveFeedbackForUser>(); foreach (int userId in Users.Keys) { basicUsers[userId] = Users[userId].AsPositiveFeedback(classifier); } return(new BasicTrainingData <IPositiveFeedbackForUser>(basicUsers)); }
private SingleUserEvaluationResults GetSingleUserEvaluationResults <TInput, TRecommendation>( IRecommendationSource <TInput, IEnumerable <TRecommendation>, TRecommendation> recSource, TInput user, IUserInputClassifier <TInput> goodBadClassifier, Func <ClassifiedUserInput <TInput>, double, ItemsForInputAndEvaluation <TInput> > inputDivisionFunc, int numRecsToTryToGet) where TInput : IInputForUser where TRecommendation : IRecommendation { // Divide into liked and unliked. // Set aside a random X% of the liked and a random X% of the unliked ClassifiedUserInput <TInput> classified = goodBadClassifier.Classify(user); ItemsForInputAndEvaluation <TInput> divided = inputDivisionFunc(classified, FractionOfInputToSetAsideForEvaluation); // Get top N recommendations // Keep count of hits and false positives List <int> recommendedIds = new List <int>(); int truePositivesForThisUser = 0; int falsePositivesForThisUser = 0; int unknownsForThisUser = 0; foreach (TRecommendation recommendation in recSource.GetRecommendations(divided.ItemsForInput, numRecsToTryToGet)) { recommendedIds.Add(recommendation.ItemId); if (divided.LikedItemsForEvaluation.Contains(recommendation.ItemId)) { truePositivesForThisUser++; } else if (divided.UnlikedItemsForEvaluation.Contains(recommendation.ItemId)) { falsePositivesForThisUser++; } else { unknownsForThisUser++; } } int falseNegativesForThisUser = divided.LikedItemsForEvaluation.Count - truePositivesForThisUser; SingleUserEvaluationResults results = new SingleUserEvaluationResults() { TruePositives = truePositivesForThisUser, FalsePositives = falsePositivesForThisUser, Unknowns = unknownsForThisUser, FalseNegatives = falseNegativesForThisUser, }; return(results); }
public IPositiveFeedbackForUser AsPositiveFeedback(IUserInputClassifier <MalUserListEntries> classifier, Predicate <int> additionalOkToRecommendPredicate) { ClassifiedUserInput <MalUserListEntries> classified = classifier.Classify(this); HashSet <int> basicFeedback = new HashSet <int>(classified.Liked.Entries.Select(itemIdEntryPair => itemIdEntryPair.Key)); if (additionalOkToRecommendPredicate == null) { return(new BasicPositiveFeedbackForUserWithOkToRecommendPredicate(basicFeedback, ItemIsOkToRecommend)); } else { return(new BasicPositiveFeedbackForUserWithOkToRecommendPredicate(basicFeedback, (itemId) => ItemIsOkToRecommend(itemId) && additionalOkToRecommendPredicate(itemId))); } }
/// <summary> /// /// </summary> /// <typeparam name="TInput"></typeparam> /// <typeparam name="TRecommendation"></typeparam> /// <param name="recSource">A recommendation source that has already been trained.</param> /// <param name="users">The users to use in evaluation by getting recommendations for them.</param> /// <param name="goodBadClassifier">Classifier to classify input for a user into liked items and unliked items. If an /// item was left out of the input passed to the recommendation source and it gets recommended, this determines whether /// it gets considered a true positive or a false positive.</param> /// <param name="inputDivisionFunc">Takes a user's classified input and a fraction to set aside (.2 for 20%) and returns /// a new user input object and the items that were set aside.</param> /// <param name="numRecsToTryToGet">Number of recommendations to try to get for each user.</param> /// <returns></returns> public EvaluationResults Evaluate <TInput, TRecommendation>( IRecommendationSource <TInput, IEnumerable <TRecommendation>, TRecommendation> recSource, ICollection <TInput> users, IUserInputClassifier <TInput> goodBadClassifier, Func <ClassifiedUserInput <TInput>, double, ItemsForInputAndEvaluation <TInput> > inputDivisionFunc, int numRecsToTryToGet) where TInput : IInputForUser where TRecommendation : IRecommendation { EvaluationResults results = new EvaluationResults() { TotalTruePositives = 0, TotalFalsePositives = 0, TotalUnknown = 0, TotalFalseNegatives = 0, TotalPrecision = 0, NumPrecision = 0, TotalRecall = 0, NumRecall = 0 }; foreach (TInput user in users) { SingleUserEvaluationResults userResults = GetSingleUserEvaluationResults(recSource, user, goodBadClassifier, inputDivisionFunc, numRecsToTryToGet); results.TotalTruePositives += userResults.TruePositives; results.TotalFalsePositives += userResults.FalsePositives; results.TotalUnknown += userResults.Unknowns; results.TotalFalseNegatives += userResults.FalseNegatives; if (userResults.Precision.HasValue) { results.TotalPrecision += userResults.Precision.Value; results.NumPrecision++; } if (userResults.Recall.HasValue) { results.TotalRecall += userResults.Recall.Value; results.NumRecall++; } } return(results); }
public IPositiveFeedbackForUser AsPositiveFeedback(IUserInputClassifier <MalUserListEntries> classifier) { return(AsPositiveFeedback(classifier, null)); }
public IPositiveFeedbackForUser AsPositiveFeedback(IUserInputClassifier<MalUserListEntries> classifier, Predicate<int> additionalOkToRecommendPredicate) { ClassifiedUserInput<MalUserListEntries> classified = classifier.Classify(this); HashSet<int> basicFeedback = new HashSet<int>(classified.Liked.Entries.Select(itemIdEntryPair => itemIdEntryPair.Key)); if (additionalOkToRecommendPredicate == null) { return new BasicPositiveFeedbackForUserWithOkToRecommendPredicate(basicFeedback, ItemIsOkToRecommend); } else { return new BasicPositiveFeedbackForUserWithOkToRecommendPredicate(basicFeedback, (itemId) => ItemIsOkToRecommend(itemId) && additionalOkToRecommendPredicate(itemId)); } }
public IPositiveFeedbackForUser AsPositiveFeedback(IUserInputClassifier<MalUserListEntries> classifier) { return AsPositiveFeedback(classifier, null); }
public AnimeRecsTrainingData(TUnderlyingTrainingData trainingData, IUserInputClassifier <TUserRatings> recommenderRatingClassifier) { TrainingData = trainingData; RecommenderRatingClassifier = recommenderRatingClassifier; }