public void preferencesFetchedOnlyOnce() { var dataModelMock = new DynamicMock(typeof(IDataModel)); var itemSimilarityMock = new DynamicMock(typeof(IItemSimilarity)); var candidateItemsStrategyMock = new DynamicMock(typeof(ICandidateItemsStrategy)); var mostSimilarItemsCandidateItemsStrategyMock = new DynamicMock(typeof(IMostSimilarItemsCandidateItemsStrategy)); IPreferenceArray preferencesFromUser = new GenericUserPreferenceArray( new List <IPreference>() { new GenericPreference(1L, 1L, 5.0f), new GenericPreference(1L, 2L, 4.0f) }); dataModelMock.ExpectAndReturn("GetMinPreference", float.NaN); dataModelMock.ExpectAndReturn("GetMaxPreference", float.NaN); dataModelMock.ExpectAndReturn("GetPreferencesFromUser", preferencesFromUser, 1L); var dataModel = (IDataModel)dataModelMock.MockInstance; candidateItemsStrategyMock.ExpectAndReturn("GetCandidateItems", new FastIDSet(new long[] { 3L, 4L }), 1L, preferencesFromUser, dataModel); itemSimilarityMock.ExpectAndReturn("ItemSimilarities", new double[] { 0.5, 0.3 }, 3L, preferencesFromUser.GetIDs()); itemSimilarityMock.ExpectAndReturn("ItemSimilarities", new double[] { 0.4, 0.1 }, 4L, preferencesFromUser.GetIDs()); //EasyMock.replay(dataModel, itemSimilarity, candidateItemsStrategy, mostSimilarItemsCandidateItemsStrategy); IRecommender recommender = new GenericItemBasedRecommender((IDataModel)dataModel, (IItemSimilarity)itemSimilarityMock.MockInstance, (ICandidateItemsStrategy)candidateItemsStrategyMock.MockInstance, (IMostSimilarItemsCandidateItemsStrategy)mostSimilarItemsCandidateItemsStrategyMock.MockInstance); recommender.Recommend(1L, 3); dataModelMock.Verify(); itemSimilarityMock.Verify(); candidateItemsStrategyMock.Verify(); mostSimilarItemsCandidateItemsStrategyMock.Verify(); //EasyMock.verify(dataModel, itemSimilarity, candidateItemsStrategy, mostSimilarItemsCandidateItemsStrategy); }
public List <MovieRecommendationDto> GetRecommendedMovies(int[] preferredMovieIds) { var dataModel = GetDataModel(); // recommendation is performed for the user that is missed in the preferences data var plusAnonymModel = new PlusAnonymousUserDataModel(dataModel); var prefArr = new GenericUserPreferenceArray(preferredMovieIds.Length); prefArr.SetUserID(0, PlusAnonymousUserDataModel.TEMP_USER_ID); for (int i = 0; i < preferredMovieIds.Length; i++) { prefArr.SetItemID(i, preferredMovieIds[i]); // in this example we have no ratings of movies preferred by the user prefArr.SetValue(i, 5); // lets assume max rating } plusAnonymModel.SetTempPrefs(prefArr); var similarity = new LogLikelihoodSimilarity(plusAnonymModel); var neighborhood = new NearestNUserNeighborhood(15, similarity, plusAnonymModel); var recommender = new GenericUserBasedRecommender(plusAnonymModel, neighborhood, similarity); var recommendedItems = recommender.Recommend(PlusAnonymousUserDataModel.TEMP_USER_ID, 5, null); var movieIds = recommendedItems.Select(ri => (int)ri.GetItemID()).ToArray(); var movieIdToTitleDictionary = _unitOfWork.MovieRepository.GetMovieIdToTileDictionary(movieIds); var recommendedMovies = new List <MovieRecommendationDto>(); foreach (var item in recommendedItems) { var movieId = (int)item.GetItemID(); var movieTitle = movieIdToTitleDictionary[movieId]; recommendedMovies.Add( new MovieRecommendationDto { MovieId = movieId, MovieTitle = movieTitle, Rating = item.GetValue() }); } return(recommendedMovies); }
public ActionResult Recommend(string filmIdsJson) { var filmIds = (new JavaScriptSerializer()).Deserialize <long[]>(filmIdsJson); var pathToDataFile = Path.Combine(System.Web.HttpRuntime.AppDomainAppPath, "data/albums.dat"); if (dataModel == null) { try { dataModel = new FileDataModel(pathToDataFile, false, FileDataModel.DEFAULT_MIN_RELOAD_INTERVAL_MS, false); } catch (Exception e) { var exe = e.ToString(); } } var plusAnonymModel = new PlusAnonymousUserDataModel(dataModel); var prefArr = new GenericUserPreferenceArray(filmIds.Length); prefArr.SetUserID(0, PlusAnonymousUserDataModel.TEMP_USER_ID); for (int i = 0; i < filmIds.Length; i++) { prefArr.SetItemID(i, filmIds[i]); prefArr.SetValue(i, 5); // lets assume max rating } plusAnonymModel.SetTempPrefs(prefArr); var similarity = new LogLikelihoodSimilarity(plusAnonymModel); var neighborhood = new NearestNUserNeighborhood(15, similarity, plusAnonymModel); var recommender = new GenericBooleanPrefUserBasedRecommender(plusAnonymModel, neighborhood, similarity); var recommendedItems = recommender.Recommend(PlusAnonymousUserDataModel.TEMP_USER_ID, 5, null); return(Json(recommendedItems.Select(ri => new Dictionary <string, object>() { { "id", ri.GetItemID() }, { "rating", ri.GetValue() }, }).ToArray())); }
public void testStrategy() { FastIDSet itemIDsFromUser123 = new FastIDSet(); itemIDsFromUser123.Add(1L); FastIDSet itemIDsFromUser456 = new FastIDSet(); itemIDsFromUser456.Add(1L); itemIDsFromUser456.Add(2L); List <IPreference> prefs = new List <IPreference>(); prefs.Add(new GenericPreference(123L, 1L, 1.0f)); prefs.Add(new GenericPreference(456L, 1L, 1.0f)); IPreferenceArray preferencesForItem1 = new GenericItemPreferenceArray(prefs); var dataModelMock = new DynamicMock(typeof(IDataModel)); dataModelMock.ExpectAndReturn("GetPreferencesForItem", preferencesForItem1, (1L)); dataModelMock.ExpectAndReturn("GetItemIDsFromUser", itemIDsFromUser123, (123L)); dataModelMock.ExpectAndReturn("GetItemIDsFromUser", itemIDsFromUser456, (456L)); IPreferenceArray prefArrayOfUser123 = new GenericUserPreferenceArray(new List <IPreference>() { new GenericPreference(123L, 1L, 1.0f) }); ICandidateItemsStrategy strategy = new PreferredItemsNeighborhoodCandidateItemsStrategy(); //EasyMock.replay(dataModel); FastIDSet candidateItems = strategy.GetCandidateItems(123L, prefArrayOfUser123, (IDataModel)dataModelMock.MockInstance); Assert.AreEqual(1, candidateItems.Count()); Assert.True(candidateItems.Contains(2L)); dataModelMock.Verify(); // EasyMock.verify(dataModel); }
/// <summary> /// 推荐 /// </summary> /// <param name="pageIndex">当前页</param> /// <param name="pageSize">页容量</param> /// <param name="showCount">显示数量</param> /// <returns></returns> public List <Books> RecommendBooks(int pageIndex, int pageSize, int showCount) { #region 推荐 List <Books> books = null; if (Session["user"] != null) { Users user = Session["user"] as Users; #region 构建用户行为数组 var loglist = logbll.LoadEntities(c => c.userID == user.Id).ToList(); StringBuilder sb = new StringBuilder(); if (loglist.Count > 0) { sb.Append("["); int j = 0; foreach (var item in loglist) { j++; sb.Append(item.itemID.ToString()); if (j != loglist.Count) { sb.Append(","); } } sb.Append("]"); } #endregion if (string.IsNullOrEmpty(sb.ToString())) { //冷启动 books = booksbll.LoadEntities(c => true).OrderByDescending(c => c.rating).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); } else { var filmIds = (new JavaScriptSerializer()).Deserialize <long[]>(sb.ToString()); var logmodel = settingbll.LoadEntities(c => c.id == 16).FirstOrDefault(); string path = ""; if (logmodel != null && logmodel.value == "true") { path = "data/ratings1.dat"; } else { path = "data/ratings.dat"; } var pathToDataFile = Path.Combine(System.Web.HttpRuntime.AppDomainAppPath, path); if (dataModel == null) { dataModel = new FileDataModel(pathToDataFile, false, FileDataModel.DEFAULT_MIN_RELOAD_INTERVAL_MS, false); } var plusAnonymModel = new PlusAnonymousUserDataModel(dataModel); var prefArr = new GenericUserPreferenceArray(filmIds.Length); prefArr.SetUserID(0, PlusAnonymousUserDataModel.TEMP_USER_ID); for (int i = 0; i < filmIds.Length; i++) { prefArr.SetItemID(i, filmIds[i]); prefArr.SetValue(i, 5); // lets assume max rating } plusAnonymModel.SetTempPrefs(prefArr); var similarity = new LogLikelihoodSimilarity(plusAnonymModel); var neighborhood = new NearestNUserNeighborhood(15, similarity, plusAnonymModel); var recommender = new GenericUserBasedRecommender(plusAnonymModel, neighborhood, similarity); var recommendedItems = recommender.Recommend(PlusAnonymousUserDataModel.TEMP_USER_ID, showCount, null); List <Books> newbooks = new List <Books>(); foreach (var item in recommendedItems) { int bid = Convert.ToInt32(item.GetItemID()); newbooks.Add(booksbll.LoadEntities(c => c.Id == bid).FirstOrDefault()); } books = newbooks.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); } } else //不推荐 { books = booksbll.LoadEntities(c => true).OrderByDescending(c => c.rating).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); } #endregion return(books.Count() <= 0 ? booksbll.LoadEntities(c => true).OrderByDescending(c => c.rating).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList() : books); }
public ActionResult GetRecommendedbooks() { var csv = new CsvReader(new StreamReader(System.Web.HttpContext.Current.Server.MapPath("~/App_Data/books.csv"))); var records = csv.GetRecords <BookRecord>().ToList(); int favouriteGenre = db.Users.Where(u => u.UserName == User.Identity.Name).Select(u => u.genreID).SingleOrDefault(); var userRentals = db.Rentals.Where(m => m.rentalUser == User.Identity.Name).Join(db.Books, r => r.rentalBook, m => m.bookName, (r, m) => new { genreId = m.genreID, bookName = m.bookName, rentalUer = r.rentalUser }); if (userRentals.Count() == 0) { return(Json(new Dictionary <string, object>() { { "book_id", 0 }, { "rating", 0 }, })); } else if (userRentals.Where(m => m.genreId == favouriteGenre).Count() != 0) { userRentals = userRentals.Where(m => m.genreId == favouriteGenre); } long[] bookIdsTemp = new long[userRentals.Count()]; int bookCounter = 0; foreach (var item in userRentals) { foreach (var record in records) { if (item.bookName == record.title) { if (!bookIdsTemp.Contains(record.bookId)) { bookIdsTemp[bookCounter] = record.bookId; bookCounter++; } } } } long[] bookIds = new long[bookCounter]; for (int i = 0; i < bookCounter; i++) { bookIds[i] = bookIdsTemp[i]; } var dataModel = GetDataModel(); // recommendation is performed for the user that is missed in the preferences data var plusAnonymModel = new PlusAnonymousUserDataModel(dataModel); var prefArr = new GenericUserPreferenceArray(userRentals.Count()); prefArr.SetUserID(0, PlusAnonymousUserDataModel.TEMP_USER_ID); for (int i = 0; i < bookIds.Length; i++) { prefArr.SetItemID(i, bookIds[i]); // in this example we have no ratings of books preferred by the user prefArr.SetValue(i, 5); // lets assume max rating } plusAnonymModel.SetTempPrefs(prefArr); var similarity = new LogLikelihoodSimilarity(plusAnonymModel); var neighborhood = new NearestNUserNeighborhood(15, similarity, plusAnonymModel); var recommender = new GenericUserBasedRecommender(plusAnonymModel, neighborhood, similarity); var recommendedItems = recommender.Recommend(PlusAnonymousUserDataModel.TEMP_USER_ID, 1, null); if (recommendedItems.Count() == 0) { return(Json(new Dictionary <string, object>() { { "book_id", 0 }, { "rating", 0 }, })); } return(Json(recommendedItems.Select(ri => new Dictionary <string, object>() { { "book_id", ri.GetItemID() }, { "rating", ri.GetValue() }, }).ToArray()[0])); }
protected void processLine <T>(string line, FastByIDMap <T> data, FastByIDMap <FastByIDMap <DateTime?> > timestamps, bool fromPriorData) { bool flag2; int num5; PreferenceArray array2; int num6; float num7; if ((line.Length == 0) || (line[0] == COMMENT_CHAR)) { return; } string[] strArray = line.Split(new char[] { this.delimiter }); string str = strArray[0]; string str2 = strArray[1]; string str3 = strArray[2]; bool flag = strArray.Length > 3; string timestampString = flag ? strArray[3] : null; long key = this.readUserIDFromString(str); long itemID = this.readItemIDFromString(str2); if (this.transpose) { long num3 = key; key = itemID; itemID = num3; } T local = data.get(key); if (!fromPriorData) { IEnumerable <Preference> source = (IEnumerable <Preference>)local; if (flag || !string.IsNullOrWhiteSpace(str3)) { num7 = float.Parse(str3, CultureInfo.InvariantCulture); flag2 = false; if (this.uniqueUserItemCheck && (source != null)) { foreach (Preference preference in source) { if (preference.getItemID() == itemID) { flag2 = true; preference.setValue(num7); break; } } } if (!flag2) { if (source == null) { source = new List <Preference>(5); data.put(key, (T)source); } if (source is IList <Preference> ) { ((IList <Preference>)source).Add(new GenericPreference(key, itemID, num7)); } } this.addTimestamp(key, itemID, timestampString, timestamps); return; } if (source != null) { IEnumerator <Preference> enumerator = ((IEnumerable <Preference>)source.ToArray <Preference>()).GetEnumerator(); while (enumerator.MoveNext()) { Preference current = enumerator.Current; if (current.getItemID() == itemID) { if (source is IList <Preference> ) { ((IList <Preference>)local).Remove(current); } break; } } } removeTimestamp(key, itemID, timestamps); return; } PreferenceArray array = (PreferenceArray)local; if (flag || !string.IsNullOrWhiteSpace(str3)) { num7 = float.Parse(str3, CultureInfo.InvariantCulture); flag2 = false; if (this.uniqueUserItemCheck && (array != null)) { for (num5 = 0; num5 < array.length(); num5++) { if (array.getItemID(num5) == itemID) { flag2 = true; array.setValue(num5, num7); break; } } } } else { if (array != null) { flag2 = false; int num4 = array.length(); for (num5 = 0; num5 < num4; num5++) { if (array.getItemID(num5) == itemID) { flag2 = true; break; } } if (flag2) { if (num4 == 1) { data.remove(key); } else { array2 = new GenericUserPreferenceArray(num4 - 1); num5 = 0; for (num6 = 0; num5 < num4; num6++) { if (array.getItemID(num5) == itemID) { num6--; } else { array2.set(num6, array.get(num5)); } num5++; } data.put(key, (T)array2); } } } removeTimestamp(key, itemID, timestamps); goto Label_02F1; } if (!flag2) { if (array == null) { array = new GenericUserPreferenceArray(1); } else { array2 = new GenericUserPreferenceArray(array.length() + 1); num5 = 0; for (num6 = 1; num5 < array.length(); num6++) { array2.set(num6, array.get(num5)); num5++; } array = array2; } array.setUserID(0, key); array.setItemID(0, itemID); array.setValue(0, num7); data.put(key, (T)array); } Label_02F1: this.addTimestamp(key, itemID, timestampString, timestamps); }
/// <p> /// Reads one line from the input file and adds the data to a {@link FastByIDMap} data structure which maps user IDs /// to preferences. This assumes that each line of the input file corresponds to one preference. After /// reading a line and determining which user and item the preference pertains to, the method should look to /// see if the data contains a mapping for the user ID already, and if not, add an empty data structure of preferences /// as appropriate to the data. /// </p> /// /// <p> /// Note that if the line is empty or begins with '#' it will be ignored as a comment. /// </p> /// /// @param line /// line from input data file /// @param data /// all data read so far, as a mapping from user IDs to preferences /// @param fromPriorData an implementation detail -- if true, data will map IDs to /// {@link PreferenceArray} since the framework is attempting to read and update raw /// data that is already in memory. Otherwise it maps to {@link Collection}s of /// {@link Preference}s, since it's reading fresh data. Subclasses must be prepared /// to handle this wrinkle. protected void processLine <T>(string line, FastByIDMap <T> data, FastByIDMap <FastByIDMap <DateTime?> > timestamps, bool fromPriorData) { // Ignore empty lines and comments if (line.Length == 0 || line[0] == COMMENT_CHAR) { return; } var tokens = SplitLine(line); string userIDString = tokens[0]; string itemIDString = tokens[1]; string preferenceValueString = tokens[2]; bool hasTimestamp = tokens.Length > 3; string timestampString = hasTimestamp ? tokens[3] : null; long userID = readUserIDFromString(userIDString); long itemID = readItemIDFromString(itemIDString); if (transpose) { long tmp = userID; userID = itemID; itemID = tmp; } // This is kind of gross but need to handle two types of storage var maybePrefs = data.Get(userID); if (fromPriorData) { // Data are PreferenceArray IPreferenceArray prefs = (IPreferenceArray)maybePrefs; if (!hasTimestamp && String.IsNullOrWhiteSpace(preferenceValueString)) { // Then line is of form "userID,itemID,", meaning remove if (prefs != null) { bool exists = false; int length = prefs.Length(); for (int i = 0; i < length; i++) { if (prefs.GetItemID(i) == itemID) { exists = true; break; } } if (exists) { if (length == 1) { data.Remove(userID); } else { IPreferenceArray newPrefs = new GenericUserPreferenceArray(length - 1); for (int i = 0, j = 0; i < length; i++, j++) { if (prefs.GetItemID(i) == itemID) { j--; } else { newPrefs.Set(j, prefs.Get(i)); } } data.Put(userID, (T)newPrefs); } } } removeTimestamp(userID, itemID, timestamps); } else { float preferenceValue = float.Parse(preferenceValueString, CultureInfo.InvariantCulture); bool exists = false; if (uniqueUserItemCheck && prefs != null) { for (int i = 0; i < prefs.Length(); i++) { if (prefs.GetItemID(i) == itemID) { exists = true; prefs.SetValue(i, preferenceValue); break; } } } if (!exists) { if (prefs == null) { prefs = new GenericUserPreferenceArray(1); } else { IPreferenceArray newPrefs = new GenericUserPreferenceArray(prefs.Length() + 1); for (int i = 0, j = 1; i < prefs.Length(); i++, j++) { newPrefs.Set(j, prefs.Get(i)); } prefs = newPrefs; } prefs.SetUserID(0, userID); prefs.SetItemID(0, itemID); prefs.SetValue(0, preferenceValue); data.Put(userID, (T)prefs); } } addTimestamp(userID, itemID, timestampString, timestamps); } else { // Data are IEnumerable<Preference> IEnumerable <IPreference> prefs = ((IEnumerable <IPreference>)maybePrefs); if (!hasTimestamp && String.IsNullOrWhiteSpace(preferenceValueString)) { // Then line is of form "userID,itemID,", meaning remove if (prefs != null) { // remove pref var prefsIterator = ((IEnumerable <IPreference>)prefs.ToArray()).GetEnumerator(); while (prefsIterator.MoveNext()) { IPreference pref = prefsIterator.Current; if (pref.GetItemID() == itemID) { if (prefs is IList <IPreference> ) { ((IList <IPreference>)maybePrefs).Remove(pref);// prefsIterator.remove() } break; } } } removeTimestamp(userID, itemID, timestamps); } else { float preferenceValue = float.Parse(preferenceValueString, CultureInfo.InvariantCulture); bool exists = false; if (uniqueUserItemCheck && prefs != null) { foreach (IPreference pref in prefs) { if (pref.GetItemID() == itemID) { exists = true; pref.SetValue(preferenceValue); break; } } } if (!exists) { if (prefs == null) { prefs = new List <IPreference>(5); data.Put(userID, (T)prefs); } if (prefs is IList <IPreference> ) { ((IList <IPreference>)prefs).Add(new GenericPreference(userID, itemID, preferenceValue)); } } addTimestamp(userID, itemID, timestampString, timestamps); } } }