public double Estimate(Item item) { Pair <Item, Item> pair = new Pair <Item, Item>(toItem, item); if (rescorer.IsFiltered(pair)) { return(Double.NaN); } double originalEstimate = correlation.GetItemCorrelation(toItem, item); return(rescorer.Rescore(pair, originalEstimate)); }
public double Estimate(User user) { Pair <User, User> pair = new Pair <User, User>(toUser, user); if (rescorer.IsFiltered(pair)) { return(Double.NaN); } double originalEstimate = correlation.GetUserCorrelation(toUser, user); return(rescorer.Rescore(pair, originalEstimate)); }
/** * {@inheritDoc} */ public override IList <RecommendedItem> Recommend(Object userID, int howMany, Rescorer <Item> rescorer) { if (userID == null || rescorer == null) { throw new ArgumentNullException("userID or rescorer is null"); } if (howMany < 1) { throw new ArgumentException("howMany must be at least 1"); } CheckClustersBuilt(); if (log.IsDebugEnabled) { log.Debug("Recommending items for user ID '" + userID + '\''); } IList <RecommendedItem> recommended; topRecsByUserID.TryGetValue(userID, out recommended); if (recommended == null) { recommended = new List <RecommendedItem>(); return(recommended); } User theUser = this.DataModel.GetUser(userID); List <RecommendedItem> rescored = new List <RecommendedItem>(recommended.Count); // Only add items the user doesn't already have a preference for. // And that the rescorer doesn't "reject". foreach (RecommendedItem recommendedItem in recommended) { Item item = recommendedItem.Item; if (rescorer.IsFiltered(item)) { continue; } if (theUser.GetPreferenceFor(item.ID) == null && !double.IsNaN(rescorer.Rescore(item, recommendedItem.Value))) { rescored.Add(recommendedItem); } } rescored.Sort(new ByRescoreComparator(rescorer)); return(rescored); }
public double Estimate(Item item) { RunningAverage average = new FullRunningAverage(); foreach (Item toItem in toItems) { Pair <Item, Item> pair = new Pair <Item, Item>(toItem, item); if (rescorer.IsFiltered(pair)) { continue; } double estimate = correlation.GetItemCorrelation(toItem, item); estimate = rescorer.Rescore(pair, estimate); average.AddDatum(estimate); } return(average.Average); }
public static IList <RecommendedItem> GetTopItems(int howMany, IEnumerable <Item> allItems, Rescorer <Item> rescorer, Estimator <Item> estimator) { if (allItems == null || rescorer == null || estimator == null) { throw new ArgumentNullException("argument is null"); } LinkedList <RecommendedItem> topItems = new LinkedList <RecommendedItem>(); bool full = false; foreach (Item item in allItems) { if (item.IsRecommendable && !rescorer.IsFiltered(item)) { double preference = estimator.Estimate(item); double rescoredPref = rescorer.Rescore(item, preference); LinkedListNode <RecommendedItem> node = topItems.Last; if (!Double.IsNaN(rescoredPref) && (!full || rescoredPref > node.Value.Value)) { // I think this is faster than Collections.binarySearch() over a LinkedList since our // comparisons are cheap, which binarySearch() economizes at the expense of more traversals. // We also know that the right position tends to be at the end of the list. while (node != null && node.Previous != null) { node = node.Previous; if (rescoredPref <= node.Value.Value) { node = node.Next; break; } if (node == topItems.First) { break; } } RecommendedItem newItem = new GenericRecommendedItem(item, rescoredPref); if (node == null) { topItems.AddFirst(newItem); } else if (topItems.Count == 1) { // special handling in this case is to avoid problems // with negative preferences. Imagine -0.3 being added // first followed by -0.6. If we simply did AddAfter, // those items would be out of sequence - cc if (rescoredPref > node.Value.Value) { topItems.AddAfter(node, newItem); } else { topItems.AddBefore(node, newItem); } } else { topItems.AddAfter(node, newItem); } if (full) { topItems.RemoveLast(); } else if (topItems.Count > howMany) { full = true; topItems.RemoveLast(); } } } } List <RecommendedItem> result = new List <RecommendedItem>(topItems.Count); foreach (RecommendedItem item in topItems) { result.Add(item); } return(result); }
public static List <User> GetTopUsers(int howMany, IEnumerable <User> allUsers, Rescorer <User> rescorer, Estimator <User> estimator) { LinkedList <SimilarUser> topUsers = new LinkedList <SimilarUser>(); bool full = false; foreach (User user in allUsers) { if (rescorer.IsFiltered(user)) { continue; } double similarity = estimator.Estimate(user); double rescoredSimilarity = rescorer.Rescore(user, similarity); LinkedListNode <SimilarUser> node = topUsers.Last; if (!double.IsNaN(rescoredSimilarity) && (!full || rescoredSimilarity > node.Value.Similarity)) { //SimilarUser _user = new SimilarUser(user, similarity); SimilarUser _user = new SimilarUser(user, rescoredSimilarity); if (node == null) { topUsers.AddLast(_user); } else if (node.Previous == null) // 1 node { if (rescoredSimilarity > node.Value.Similarity) { topUsers.AddAfter(node, _user); } else { topUsers.AddBefore(node, _user); } } else { while (node != null && node.Previous != null && (node != topUsers.First)) { node = node.Previous; if (rescoredSimilarity <= node.Value.Similarity) { topUsers.AddBefore(node, _user); break; } } } if (full) { topUsers.RemoveLast(); } else if (topUsers.Count > howMany) { full = true; topUsers.RemoveLast(); } } } List <User> result = new List <User>(topUsers.Count); foreach (SimilarUser similarUser in topUsers) { result.Add(similarUser.User); } return(result); }