protected List <Rating> GetRecommendations(MyTable ratingTable, MyTable W, int K = 80, int N = 10) { MyTable recommendedTable = new MyTable(); foreach (int userId in ratingTable.Keys) { Hashtable Nu = (Hashtable)ratingTable[userId]; // ratings of user u if (!W.ContainsMainKey(userId)) // NOTE: a user bought an item which had only rated by him. { continue; } List <Link> similarUsers = GetSimilarUsers(W, userId, K); foreach (Link l in similarUsers) { int vId = l.To; // similar user v Hashtable Nv = (Hashtable)ratingTable[vId]; // ratings of user v foreach (int iId in Nv.Keys) { if (Nu.ContainsKey(iId)) { continue; } if (recommendedTable.ContainsKey(userId, iId)) { double _t = (double)recommendedTable[userId, iId]; recommendedTable[userId, iId] = _t + l.Weight; } else { recommendedTable.Add(userId, iId, l.Weight); } } } } List <Rating> recommendedItems = new List <Rating>(); foreach (int uId in recommendedTable.Keys) { List <Rating> li = new List <Rating>(); Hashtable subTable = (Hashtable)recommendedTable[uId]; foreach (int iId in subTable.Keys) { double _t = (double)subTable[iId]; li.Add(new Rating(uId, iId, _t)); } List <Rating> sortedLi = li.OrderByDescending(r => r.Score).ToList(); recommendedItems.AddRange(sortedLi.GetRange(0, Math.Min(sortedLi.Count, N))); } return(recommendedItems); }
protected MyTable GetRecommendationsByTFIDFPlusPlus(MyTable ratingTable, MyTable userTagTable, Hashtable tagUsersTable, MyTable tagItemTable, Hashtable itemTagsTable) { MyTable recommendTable = new MyTable(); int[] userIds = new int[ratingTable.Keys.Count]; ratingTable.Keys.CopyTo(userIds, 0); Parallel.ForEach(userIds, userId => { Hashtable subTable = (Hashtable)ratingTable[userId]; if (userTagTable.ContainsMainKey(userId)) { Hashtable tagTable = (Hashtable)userTagTable[userId]; foreach (int tagId in tagTable.Keys) { if (!tagItemTable.ContainsMainKey(tagId)) { continue; } Hashtable itemTable = (Hashtable)tagItemTable[tagId]; foreach (int itemId in itemTable.Keys) { // if user has rated this item if (subTable.ContainsKey(itemId)) { continue; } List <Link> n_b = (List <Link>)tagUsersTable[tagId]; // # of users who used this tag List <Link> n_i = (List <Link>)itemTagsTable[itemId]; // # of users who used this tag double wut = (double)tagTable[tagId]; double wti = (double)itemTable[itemId]; double pui = wut / Math.Log(1 + n_b.Count) * wti / Math.Log(1 + n_i.Count); lock (recommendTable) { if (recommendTable.ContainsKey(userId, itemId)) { recommendTable[userId, itemId] = (double)recommendTable[userId, itemId] + pui; } else { recommendTable.Add(userId, itemId, pui); } } } } } }); return(recommendTable); }
protected MyTable GetRecommendations(MyTable ratingTable, MyTable userTagTable, MyTable tagItemTable) { MyTable recommendTable = new MyTable(); int[] userIds = new int[ratingTable.Keys.Count]; ratingTable.Keys.CopyTo(userIds, 0); Parallel.ForEach(userIds, userId => { Hashtable subTable = (Hashtable)ratingTable[userId]; if (userTagTable.ContainsMainKey(userId)) { Hashtable tagTable = (Hashtable)userTagTable[userId]; foreach (int tagId in tagTable.Keys) { if (!tagItemTable.ContainsMainKey(tagId)) { continue; } Hashtable itemTable = (Hashtable)tagItemTable[tagId]; foreach (int itemId in itemTable.Keys) { // if user has rated this item if (subTable.ContainsKey(itemId)) { continue; } double wut = (double)tagTable[tagId]; double wti = (double)itemTable[itemId]; double p = wut * wti; lock (recommendTable) { if (recommendTable.ContainsKey(userId, itemId)) { recommendTable[userId, itemId] = (double)recommendTable[userId, itemId] + p; } else { recommendTable.Add(userId, itemId, p); } } } } } }); return(recommendTable); }
/// <summary> /// Mean average precision /// https://www.kaggle.com/c/coupon-purchase-prediction#evaluation /// </summary> /// <param name="recommended">sorted predicted ratings</param> /// <param name="test">real ratings</param> /// <returns></returns> public static double MAP(List <Rating> recommendations, List <Rating> test, int k = 5) { Hashtable recommendedRatings = Tools.GetUserItemsTable(recommendations); MyTable testTable = Tools.GetRatingTable(test); // mark int validateUserCounter = 0; double _MAP = 0.0; foreach (int userId in recommendedRatings.Keys) { if (testTable.ContainsMainKey(userId)) { List <Rating> recommendedUserRatings = (List <Rating>)recommendedRatings[userId]; Hashtable testUserRatings = (Hashtable)testTable[userId]; int length = (k > recommendedUserRatings.Count ? recommendedUserRatings.Count : k); int[] accuracy = new int[length]; int correctlyPredictedItems = 0; for (int i = 0; i < length; i++) { if (testUserRatings.ContainsKey(recommendedUserRatings[i].ItemId)) // correctly predicted { correctlyPredictedItems++; accuracy[i] = correctlyPredictedItems; } } if (correctlyPredictedItems > 0) { double APu = 0.0; // average precision of user u for (int i = 0; i < length; i++) { APu += (accuracy[i] * 1.0 / (i + 1)); } APu /= length; _MAP += APu; } validateUserCounter++; // recommended users which also in test } } if (validateUserCounter > 0) { return(_MAP / validateUserCounter); } return(0.0); }