public IRating RecommendSubject(IRater rater, ISubject subject) { var raters = ratings.Select(r => r.Rater.Id).ToArray(); var subjects = ratings.Select(r => r.Subject.Id).ToArray(); var rates = ratings.Select(r => r.Value).ToArray(); Vector[] xData = new Vector[raters.Length]; for (int i = 0; i < xData.Length; ++i) { xData[i] = Vector.FromArray(raters[i], subjects[i], 1); } VariableArray <Vector> x = Variable.Observed(xData); var Y = Variable.Observed(rates, x.Range); Variable <Vector> w = Variable.Random(new VectorGaussian(Vector.Zero(3), PositiveDefiniteMatrix.Identity(3))); Range j = Y.Range; double noise = 0.1; Y[j] = Variable.GaussianFromMeanAndVariance(Variable.InnerProduct(w, x[j]), noise); var Engine = new InferenceEngine(new ExpectationPropagation()); var WPosterior = Engine.Infer <VectorGaussian>(w); double [] ratersTest = new double[1]; ratersTest[0] = rater.Id; double [] subjectsTest = new double[1]; subjectsTest[0] = subject.Id; var yTest = BayesPointMachine(ratersTest, subjectsTest, WPosterior); var pred = Engine.Infer <DistributionStructArray <Gaussian, double> >(yTest); return(new SimpleRating(rater, subject, pred[0].Point)); }
internal override decimal Weight(IRater baseRater, IRater neighbour) { var isBaseUserCached = !_notCachedWeights.TryUpdate(baseRater.Id, false, true); var isNeighbourCached = !_notCachedWeights.TryUpdate(neighbour.Id, false, true); var areCached = isBaseUserCached && isNeighbourCached; var key = string.Format("{0}_{1}", baseRater.Id, neighbour.Id); var reverseKey = string.Format("{0}_{1}", neighbour.Id, baseRater.Id); var cachedWeight = 0M; if (areCached && _userWeightsCache.TryGetValue(key, out cachedWeight)) { return(cachedWeight); } if (areCached && _userWeightsCache.TryGetValue(reverseKey, out cachedWeight)) { return(cachedWeight); } cachedWeight = _algorithm.Weight(baseRater, neighbour); _userWeightsCache[key] = cachedWeight; return(cachedWeight); }
/// <summary> /// Get a list of all users and their ratings on every article /// </summary> public UserArticleRatingsTable GetUserArticleRatingsTable(IRater rater) { UserArticleRatingsTable table = new UserArticleRatingsTable(); table.UserIndexToID = db.Users.OrderBy(x => x.UserID).Select(x => x.UserID).Distinct().ToList(); table.ArticleIndexToID = db.Articles.OrderBy(x => x.ArticleID).Select(x => x.ArticleID).Distinct().ToList(); foreach (int userId in table.UserIndexToID) { table.Users.Add(new UserArticleRatings(userId, table.ArticleIndexToID.Count)); } var userArticleRatingGroup = db.UserActions .GroupBy(x => new { x.UserID, x.ArticleID }) .Select(g => new { g.Key.UserID, g.Key.ArticleID, Rating = rater.GetRating(g.ToList()) }) .ToList(); foreach (var userAction in userArticleRatingGroup) { int userIndex = table.UserIndexToID.IndexOf(userAction.UserID); int articleIndex = table.ArticleIndexToID.IndexOf(userAction.ArticleID); table.Users[userIndex].ArticleRatings[articleIndex] = userAction.Rating; } return(table); }
internal override decimal Weight(IRater baseRater, IRater neighbour) { var helper = new RatingService(); var baseSum = baseRater.Ratings.Sum(p => p.Value * p.Value); var neighSum = neighbour.Ratings.Sum(p => p.Value * p.Value); var denominator = (decimal)(Math.Sqrt(baseSum) * Math.Sqrt(neighSum)); var sum = 0M; foreach (var pair in helper.GetCommonRatings(baseRater, neighbour)) { var ratingBase = (decimal)pair.FirstRating.Value; var ratingNeigh = (decimal)pair.SecondRating.Value; sum += ratingBase * ratingNeigh; } if (denominator == 0) { return(0); } var result = sum / denominator; return(result); }
public UserCollaborativeFilterRecommender(IComparer userComparer, IRater implicitRater, int numberOfNeighbors, int latentFeatures) { comparer = userComparer; rater = implicitRater; neighborCount = numberOfNeighbors; latentUserFeatureCount = latentFeatures; }
public virtual IEnumerable <IRating> RecommendSubjects(IRater rater, IEnumerable <ISubject> subjects, int take = -1, int skip = 0) { var dict = new Dictionary <ISubject, IRating>(); foreach (var subject in subjects) { if (!dict.ContainsKey(subject)) { dict[subject] = RecommendSubject(rater, subject); } } var sortedList = dict.Values.Where(p => p != null).Where(p => p.Value != null).OrderByDescending(p => p.Value).AsEnumerable(); if (skip > 0) { sortedList = sortedList.Skip(skip); } if (take > 0) { sortedList = sortedList.Take(take); } return(sortedList); }
public virtual IRating RecommendSubject(IRater rater, ISubject subject) { var alreadyRated = Ratings.Find(p => p.Rater.Id == rater.Id && p.Subject.Id == subject.Id); if (alreadyRated != null) { return(alreadyRated); } var ratings = Ratings.Where(p => p.Subject.Id == subject.Id && p.Rater.Id != rater.Id).ToList(); if (!ratings.Any()) { return(null); } var meanVote = RatersMeanVote(rater); var options = new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }; var sumBag = new ConcurrentBag <decimal>(); var weightSumBag = new ConcurrentBag <decimal>(); Parallel.ForEach(ratings, options, rating => { try { var weight = Weight(rater, rating.Rater); var mean = RatersMeanVote(rating.Rater); var value = (decimal)rating.Value; var diff = value - mean; var val = weight * diff; weightSumBag.Add(weight); sumBag.Add(val); } catch (Exception) { } }); var sum = sumBag.Sum(); var weightSum = weightSumBag.Sum(); if (weightSum == 0) { return(null); } var kappa = 1 / weightSum; var result = meanVote + kappa * sum; var res = (double)result; var rate = new SimpleRating(rater, subject, res); return(rate); }
protected virtual void Initialize(IRater firstRater, IRater secondRater) //O(nlogn) { FirstRater = firstRater; SecondRater = secondRater; RatingsFirstSort = firstRater.Ratings.OrderBy(p => p.Subject.Id); RatingsSecondSort = secondRater.Ratings.OrderBy(p => p.Subject.Id); IndexFirst = 0; IndexSecond = 0; CountFirst = RatingsFirstSort.Count(); CountSecond = RatingsSecondSort.Count(); }
internal override decimal Weight(IRater baseRater, IRater neighbour) { var weight = (double)_algorithm.Weight(baseRater, neighbour); if (weight >= 0) { return((decimal)Math.Pow(weight, Ro)); } return((decimal) - Math.Pow(-weight, Ro)); }
protected internal virtual decimal RatersMeanVote(IRater rater) { var sum = 0M; var count = 0; foreach (var rating in rater.Ratings) { sum += (decimal)rating.Value; ++count; } return(sum / count); }
protected internal override decimal RatersMeanVote(IRater rater) { var isCached = !_notCachedMeanVotes.TryUpdate(rater.Id, false, true); var value = 0M; if (isCached && _userMeanVotesCache.TryGetValue(rater.Id, out value)) { return(value); } value = base.RatersMeanVote(rater); _userMeanVotesCache[rater.Id] = value; return(value); }
public IRating RecommendSubject(IRater rater, ISubject subject) { var key = CreateCacheKey(rater, subject); var cachedValue = 0D; if (_cache.TryGetValue(key, out cachedValue)) { return(new SimpleRating(rater, subject, cachedValue)); } var rating = _algorithm.RecommendSubject(rater, subject); if (rating != null) { _cache[key] = rating.Value; } return(rating); }
public IEnumerable <IRating> RecommendSubjects(IRater rater, IEnumerable <ISubject> subjects, int take = -1, int skip = 0) { var cachedResults = new ConcurrentBag <IRating>(); var notCachedSubjects = new ConcurrentBag <ISubject>(); var options = new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }; Parallel.ForEach(subjects, options, subject => { var key = CreateCacheKey(rater, subject); var value = 0D; if (_cache.TryGetValue(key, out value)) { var ranking = new SimpleRating(rater, subject, value); cachedResults.Add(ranking); } else { notCachedSubjects.Add(subject); } }); var partial = _algorithm.RecommendSubjects(rater, notCachedSubjects); var results = partial.ToList(); results.AddRange(cachedResults); var sorted = results.OrderByDescending(p => p.Value).AsEnumerable(); if (skip > 0) { sorted = sorted.Skip(skip); } if (take > 0) { sorted = sorted.Take(take); } return(sorted); }
public virtual IEnumerable <Pair> GetCommonRatings(IRater firstRater, IRater secondRater) //O(n) { if (FirstRater != firstRater || SecondRater != secondRater) { Initialize(firstRater, secondRater); } while (IndexFirst < CountFirst && IndexSecond < CountSecond) { var firstRating = RatingsFirstSort.ElementAt(IndexFirst); var secondRating = RatingsSecondSort.ElementAt(IndexSecond); var pair = ProcessRatings(firstRating, secondRating); if (pair != null) { yield return(pair); } } }
internal override decimal Weight(IRater baseRater, IRater neighbour) { var helper = new RatingService(); var frequencySum = 0M; var commonRatingsSum = 0M; var baseRatingsSum = 0M; var neighRatingsSum = 0M; var baseRatingsSquareSum = 0M; var neighRatingsSquareSum = 0M; foreach (var pair in helper.GetCommonRatings(baseRater, neighbour)) { var baseRating = (decimal)pair.FirstRating.Value; var neighRating = (decimal)pair.SecondRating.Value; var frequency = GetFrequency(pair.FirstRating.Subject); frequencySum += frequency; commonRatingsSum += frequency * baseRating * neighRating; baseRatingsSum += frequency * baseRating; neighRatingsSum += frequency * neighRating; baseRatingsSquareSum += frequency * (baseRating * baseRating); neighRatingsSquareSum += frequency * (neighRating * neighRating); } var numerator = frequencySum * commonRatingsSum - baseRatingsSum * neighRatingsSum; var firstFactor = frequencySum * (baseRatingsSquareSum - baseRatingsSum * baseRatingsSum); var secondFactor = frequencySum * (neighRatingsSquareSum - neighRatingsSum * neighRatingsSum); var factors = (double)(firstFactor * secondFactor); var denominator = (decimal)Math.Sqrt(Math.Abs(factors)); if (denominator == 0) { return(0); } var result = numerator / denominator; return(result); }
public IEnumerable <IRating> RecommendSubjects(IRater rater, IEnumerable <ISubject> subjects, int take = -1, int skip = 0) { var raters = ratings.Select(r => r.Rater.Id).ToArray(); var subjectsInit = ratings.Select(r => r.Subject.Id).ToArray(); var rates = ratings.Select(r => r.Value).ToArray(); Vector[] xData = new Vector[raters.Length]; for (int i = 0; i < xData.Length; ++i) { xData[i] = Vector.FromArray(raters[i], subjectsInit[i], 1); } VariableArray <Vector> x = Variable.Observed(xData); var Y = Variable.Observed(rates, x.Range); Variable <Vector> w = Variable.Random(new VectorGaussian(Vector.Zero(3), PositiveDefiniteMatrix.Identity(3))); Range j = Y.Range; double noise = 0.1; Y[j] = Variable.GaussianFromMeanAndVariance(Variable.InnerProduct(w, x[j]), noise); var Engine = new InferenceEngine(new ExpectationPropagation()); var WPosterior = Engine.Infer <VectorGaussian>(w); var subjectsArray = subjects.ToArray(); var ratersTest = Enumerable.Repeat((double)rater.Id, subjectsArray.Length).ToArray(); var subjectsIdsTest = subjects.Select(s => (double)s.Id).ToArray(); var yTest = BayesPointMachine(ratersTest, subjectsIdsTest, WPosterior); var pred = Engine.Infer <DistributionStructArray <Gaussian, double> >(yTest); var results = new List <IRating>(); for (int i = 0; i < subjectsArray.Length; ++i) { results.Add(new SimpleRating(rater, subjectsArray[i], pred[i].Point)); } return(results.OrderBy(r => r.Value).Skip(skip).Take(take)); }
/// <summary> /// Get a list of all users and their ratings on every article /// </summary> public UserArticleRatingsTable GetUserArticleRatingsTable(IRater rater) { UserArticleRatingsTable table = new UserArticleRatingsTable(); table.UserIndexToID = db.Users.OrderBy(x => x.UserID).Select(x => x.UserID).Distinct().ToList(); table.ArticleIndexToID = db.Articles.OrderBy(x => x.ArticleID).Select(x => x.ArticleID).Distinct().ToList(); table.Ang1 = db.Articles.Select(x => x.Name).ToList(); List <string> name = new List <string>(); name = table.Ang1; foreach (int userId in table.UserIndexToID) { table.Users.Add(new UserArticleRatings(userId, table.ArticleIndexToID.Count)); } List <ArticleAndTag> articleTags = new List <ArticleAndTag>(); foreach (Article article in db.Articles) { table.art.Add(new ArticleAndTag(article.ArticleID, article.Name, article.Tags)); } var userArticleRatingGroup = db.UserActions .GroupBy(x => new { x.UserID, x.ArticleID }) .Select(g => new { g.Key.UserID, g.Key.ArticleID, Rating = rater.GetRating(g.ToList()) }) .ToList(); foreach (var userAction in userArticleRatingGroup) { int userIndex = table.UserIndexToID.IndexOf(userAction.UserID); int articleIndex = table.ArticleIndexToID.IndexOf(userAction.ArticleID); table.Users[userIndex].ArticleRatings[articleIndex] = userAction.Rating; } return(table); }
public override IEnumerable <Pair> GetCommonRatings(IRater firstRater, IRater secondRater) { var list = base.GetCommonRatings(firstRater, secondRater); foreach (var pair in list) { yield return(pair); } var tail = GetRatingTail(ref IndexFirst, CountFirst, RatingsFirstSort, firstRater, true); foreach (var pair in tail) { yield return(pair); } tail = GetRatingTail(ref IndexSecond, CountSecond, RatingsSecondSort, secondRater, false); foreach (var pair in tail) { yield return(pair); } }
internal override decimal Weight(IRater baseRater, IRater neighbour) { var helper = GetRatingService(); var baseUsersMean = RatersMeanVote(baseRater); var neighbourMean = RatersMeanVote(neighbour); var numerator = 0M; var denominatorSumBase = 0M; var denominatorSumNeigh = 0M; foreach (var pair in helper.GetCommonRatings(baseRater, neighbour)) { var ratingBase = (decimal)pair.FirstRating.Value; var ratingNeigh = (decimal)pair.SecondRating.Value; var diffBase = ratingBase - baseUsersMean; var diffNeigh = ratingNeigh - neighbourMean; numerator += diffBase * diffNeigh; denominatorSumBase += diffBase * diffBase; denominatorSumNeigh += diffNeigh * diffNeigh; } ; var tmp = (double)(denominatorSumBase * denominatorSumNeigh); var denominator = (decimal)Math.Sqrt(tmp); if (denominator == 0) { return(0); } var result = numerator / denominator; return(result); }
public ItemCollaborativeFilterRecommender(IComparer itemComparer, IRater implicitRater, int numberOfNeighbors) { comparer = itemComparer; rater = implicitRater; neighborCount = numberOfNeighbors; }
public SimpleRating(IRater rater, ISubject subject, double value) { Rater = rater; Subject = subject; Value = value; }
public UserCollaborativeFilterRecommender(IComparer userComparer, IRater implicitRater, int numberOfNeighbors) : this(userComparer, implicitRater, numberOfNeighbors, 100) { }
private string CreateCacheKey(IRater rater, ISubject subject) { return(string.Format("{0}_{1}", rater.Id, subject.Id)); }
public MatrixFactorizationRecommender(IRater implicitRater) : this(20, implicitRater) { }
public MatrixFactorizationRecommender(int features, IRater implicitRater) { numFeatures = features; learningIterations = 100; rater = implicitRater; }
public static ScoreResults Score(this IRecommender classifier, UserBehaviorDatabase db, IRater rater) { UserBehaviorTransformer ubt = new UserBehaviorTransformer(db); UserArticleRatingsTable actualRatings = ubt.GetUserArticleRatingsTable(rater); var distinctUserArticlePairs = db.UserActions.GroupBy(x => new { x.UserID, x.ArticleID }).ToList(); double score = 0.0; int count = 0; foreach (var userArticle in distinctUserArticlePairs) { int userIndex = actualRatings.UserIndexToID.IndexOf(userArticle.Key.UserID); int articleIndex = actualRatings.ArticleIndexToID.IndexOf(userArticle.Key.ArticleID); double actualRating = actualRatings.Users[userIndex].ArticleRatings[articleIndex]; if (actualRating != 0) { double predictedRating = classifier.GetRating(userArticle.Key.UserID, userArticle.Key.ArticleID); score += Math.Pow(predictedRating - actualRating, 2); count++; } } if (count > 0) { score = Math.Sqrt(score / count); } return(new ScoreResults(score)); }
internal abstract decimal Weight(IRater baseRater, IRater neighbour);
private IEnumerable <Pair> GetRatingTail(ref int index, int count, IEnumerable <IRating> ratings, IRater rater, bool isSecondFake) { var list = new LinkedList <Pair>(); while (index < count) { var rating = ratings.ElementAt(index); var ratingFake = new SimpleRating(rater, rating.Subject, _defaultValue); var pair = isSecondFake ? new Pair() { FirstRating = rating, SecondRating = ratingFake } : new Pair() { FirstRating = ratingFake, SecondRating = rating }; ++index; list.AddLast(pair); } return(list); }