public static void main(String[] args) { DataModel model = new FileDataModel(new File(args[0])); int howMany = 10; if (args.Length > 1) { howMany = Integer.parseInt(args[1]); } System.out.println("Run Items"); ItemSimilarity similarity = new EuclideanDistanceSimilarity(model); Recommender recommender = new GenericItemBasedRecommender(model, similarity); // Use an item-item recommender for (int i = 0; i < LOOPS; i++) { LoadStatistics loadStats = LoadEvaluator.runLoad(recommender, howMany); System.out.println(loadStats); } System.out.println("Run Users"); UserSimilarity userSim = new EuclideanDistanceSimilarity(model); UserNeighborhood neighborhood = new NearestNUserNeighborhood(10, userSim, model); recommender = new GenericUserBasedRecommender(model, neighborhood, userSim); for (int i = 0; i < LOOPS; i++) { LoadStatistics loadStats = LoadEvaluator.runLoad(recommender, howMany); System.out.println(loadStats); } }
public void TestHowMany() { List<User> users = new List<User>(3); users.Add(GetUser("test1", 0.1, 0.2)); users.Add(GetUser("test2", 0.2, 0.3, 0.3, 0.6)); users.Add(GetUser("test3", 0.4, 0.4, 0.5, 0.9)); users.Add(GetUser("test4", 0.1, 0.4, 0.5, 0.8, 0.9, 1.0)); users.Add(GetUser("test5", 0.2, 0.3, 0.6, 0.7, 0.1, 0.2)); DataModel dataModel = new GenericDataModel(users); IList<GenericItemCorrelation.ItemItemCorrelation> correlations = new List<GenericItemCorrelation.ItemItemCorrelation>(6); for (int i = 0; i < 6; i++) { for (int j = i + 1; j < 6; j++) { correlations.Add( new GenericItemCorrelation.ItemItemCorrelation(new GenericItem<String>(i.ToString()), new GenericItem<String>(j.ToString()), 1.0 / (1.0 + (double)i + (double)j))); } } ItemCorrelation correlation = new GenericItemCorrelation(correlations); Recommender recommender = new GenericItemBasedRecommender(dataModel, correlation); IList<RecommendedItem> fewRecommended = recommender.Recommend("test1", 2); IList<RecommendedItem> moreRecommended = recommender.Recommend("test1", 4); for (int i = 0; i < fewRecommended.Count; i++) { Assert.AreEqual(fewRecommended[i].Item, moreRecommended[i].Item); } }
public void TestRescorer() { List <User> users = new List <User>(3); users.Add(GetUser("test1", 0.1, 0.2)); users.Add(GetUser("test2", 0.2, 0.3, 0.3, 0.6)); users.Add(GetUser("test3", 0.4, 0.4, 0.5, 0.9)); DataModel dataModel = new GenericDataModel(users); Item item1 = new GenericItem <String>("0"); Item item2 = new GenericItem <String>("1"); Item item3 = new GenericItem <String>("2"); Item item4 = new GenericItem <String>("3"); ICollection <GenericItemCorrelation.ItemItemCorrelation> correlations = new List <GenericItemCorrelation.ItemItemCorrelation>(6); correlations.Add(new GenericItemCorrelation.ItemItemCorrelation(item1, item2, 1.0)); correlations.Add(new GenericItemCorrelation.ItemItemCorrelation(item1, item3, 0.5)); correlations.Add(new GenericItemCorrelation.ItemItemCorrelation(item1, item4, 0.2)); correlations.Add(new GenericItemCorrelation.ItemItemCorrelation(item2, item3, 0.7)); correlations.Add(new GenericItemCorrelation.ItemItemCorrelation(item2, item4, 0.5)); correlations.Add(new GenericItemCorrelation.ItemItemCorrelation(item3, item4, 0.9)); ItemCorrelation correlation = new GenericItemCorrelation(correlations); Recommender recommender = new GenericItemBasedRecommender(dataModel, correlation); IList <RecommendedItem> originalRecommended = recommender.Recommend("test1", 2); IList <RecommendedItem> rescoredRecommended = recommender.Recommend("test1", 2, new ReversingRescorer <Item>()); Assert.IsNotNull(originalRecommended); Assert.IsNotNull(rescoredRecommended); Assert.AreEqual(2, originalRecommended.Count); Assert.AreEqual(2, rescoredRecommended.Count); Assert.AreEqual(originalRecommended[0].Item, rescoredRecommended[1].Item); Assert.AreEqual(originalRecommended[1].Item, rescoredRecommended[0].Item); }
public void TestHowMany() { List <User> users = new List <User>(3); users.Add(GetUser("test1", 0.1, 0.2)); users.Add(GetUser("test2", 0.2, 0.3, 0.3, 0.6)); users.Add(GetUser("test3", 0.4, 0.4, 0.5, 0.9)); users.Add(GetUser("test4", 0.1, 0.4, 0.5, 0.8, 0.9, 1.0)); users.Add(GetUser("test5", 0.2, 0.3, 0.6, 0.7, 0.1, 0.2)); DataModel dataModel = new GenericDataModel(users); IList <GenericItemCorrelation.ItemItemCorrelation> correlations = new List <GenericItemCorrelation.ItemItemCorrelation>(6); for (int i = 0; i < 6; i++) { for (int j = i + 1; j < 6; j++) { correlations.Add( new GenericItemCorrelation.ItemItemCorrelation(new GenericItem <String>(i.ToString()), new GenericItem <String>(j.ToString()), 1.0 / (1.0 + (double)i + (double)j))); } } ItemCorrelation correlation = new GenericItemCorrelation(correlations); Recommender recommender = new GenericItemBasedRecommender(dataModel, correlation); IList <RecommendedItem> fewRecommended = recommender.Recommend("test1", 2); IList <RecommendedItem> moreRecommended = recommender.Recommend("test1", 4); for (int i = 0; i < fewRecommended.Count; i++) { Assert.AreEqual(fewRecommended[i].Item, moreRecommended[i].Item); } }
static void GenericItemBasedRecommenderTestByTanimotoCoefficientSimilarity() { Console.WriteLine("GenericItemBasedRecommenderTestByTanimotoCoefficientSimilarity"); System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); var model = new FileDataModel(filePath); ItemSimilarity similarity = new TanimotoCoefficientSimilarity(model); var recommender = new GenericItemBasedRecommender(model, similarity); var iter = model.getUserIDs(); while (iter.MoveNext()) { var userId = iter.Current; var recommendedItems = recommender.recommend(userId, 5); Console.Write("uid:" + userId); foreach (var ritem in recommendedItems) { Console.Write("(" + ritem.getItemID() + "," + ritem.getValue() + ")"); } Console.WriteLine(); } watch.Stop(); Console.WriteLine(watch.ElapsedMilliseconds); }
public Result RecommendPearsonCorrelationSimilarity(int userId, int movieId) { Result result = new Result(); dataModel = new FileDataModel(PathToDataFile, false, FileDataModel.DEFAULT_MIN_RELOAD_INTERVAL_MS, false, ",", userId, movieId); var removedPrefs = GenericDataModel.preferenceFromUsersRemoved.Values; var valueToCompare = removedPrefs.FirstOrDefault(i => i.GetItemID() == movieId).GetValue(); var similarity = new PearsonCorrelationSimilarity(dataModel); var recommender = new GenericItemBasedRecommender(dataModel, similarity); var preferences = recommender.EstimatePreference(userId, movieId); result.PredictedValue = preferences; result.RealValue = removedPrefs.First().GetValue(); return result; }
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 void TestRescorer() { List<User> users = new List<User>(3); users.Add(GetUser("test1", 0.1, 0.2)); users.Add(GetUser("test2", 0.2, 0.3, 0.3, 0.6)); users.Add(GetUser("test3", 0.4, 0.4, 0.5, 0.9)); DataModel dataModel = new GenericDataModel(users); Item item1 = new GenericItem<String>("0"); Item item2 = new GenericItem<String>("1"); Item item3 = new GenericItem<String>("2"); Item item4 = new GenericItem<String>("3"); ICollection<GenericItemCorrelation.ItemItemCorrelation> correlations = new List<GenericItemCorrelation.ItemItemCorrelation>(6); correlations.Add(new GenericItemCorrelation.ItemItemCorrelation(item1, item2, 1.0)); correlations.Add(new GenericItemCorrelation.ItemItemCorrelation(item1, item3, 0.5)); correlations.Add(new GenericItemCorrelation.ItemItemCorrelation(item1, item4, 0.2)); correlations.Add(new GenericItemCorrelation.ItemItemCorrelation(item2, item3, 0.7)); correlations.Add(new GenericItemCorrelation.ItemItemCorrelation(item2, item4, 0.5)); correlations.Add(new GenericItemCorrelation.ItemItemCorrelation(item3, item4, 0.9)); ItemCorrelation correlation = new GenericItemCorrelation(correlations); Recommender recommender = new GenericItemBasedRecommender(dataModel, correlation); IList<RecommendedItem> originalRecommended = recommender.Recommend("test1", 2); IList<RecommendedItem> rescoredRecommended = recommender.Recommend("test1", 2, new ReversingRescorer<Item>()); Assert.IsNotNull(originalRecommended); Assert.IsNotNull(rescoredRecommended); Assert.AreEqual(2, originalRecommended.Count); Assert.AreEqual(2, rescoredRecommended.Count); Assert.AreEqual(originalRecommended[0].Item, rescoredRecommended[1].Item); Assert.AreEqual(originalRecommended[1].Item, rescoredRecommended[0].Item); }
static void Main(string[] args) { // load movies var movies = new List <MovieRecord>(); using (TextReader reader = File.OpenText(@"data/movies.csv")) { CsvReader csv = new CsvReader(reader); csv.Configuration.Delimiter = ","; csv.Configuration.MissingFieldFound = null; while (csv.Read()) { movies.Add(csv.GetRecord <MovieRecord>()); } } // load users List <int> users = new List <int>(); using (TextReader reader = File.OpenText(@"data/ratings.csv")) { CsvReader csv = new CsvReader(reader); csv.Configuration.Delimiter = ","; csv.Configuration.MissingFieldFound = null; while (csv.Read()) { if (int.TryParse(csv.GetField(0), out int id)) { if (!users.Contains(id)) { users.Add(id); } } } } // load data model var model = new FileDataModel("data/ratings.csv", false, FileDataModel.DEFAULT_MIN_RELOAD_INTERVAL_MS, false); //init values string similarityType = "Cosine Similarity"; string recommenderType = "Userbased"; int neighborhoodSize = 125; int resultCount = 10; List <int> movieIdPredList = new List <int>(); List <int> userIdPredList = new List <int>(); //default recommender AbstractSimilarity similarity = new UncenteredCosineSimilarity(model); var neighborhood = new NearestNUserNeighborhood(neighborhoodSize, similarity, model); AbstractRecommender recommender = new GenericUserBasedRecommender(model, neighborhood, similarity); string input = ""; while (input != "X") { Console.WriteLine(); Console.WriteLine("Was möchten Sie tun?"); Console.WriteLine("I - Umschalten auf Item-based Ansatz"); Console.WriteLine("U - Umschalten auf User-based Ansatz"); Console.WriteLine("DE - Umschalten auf Cosine Similarity"); Console.WriteLine("PE - Umschalten auf Pearson Correlation"); Console.WriteLine("N - Anzahl der Nachbarn festlegen"); Console.WriteLine("C - Konfiguration neu erstellen und Datendatei neu lesen"); Console.WriteLine("O - Aktuelle Konfiguration ausgeben"); Console.WriteLine("E - Empfehlung durchführen"); Console.WriteLine("P - Prediction für spezifischen Film durchführen"); Console.WriteLine("UADD - Benutzer zur Liste für Vorschläge hinzufügen"); Console.WriteLine("MADD - Film zur Filmliste hinzufügen"); Console.WriteLine("UCLEAR - Benutzerliste leeren"); Console.WriteLine("MCLEAR - Filmliste leeren"); Console.WriteLine("X - Programm beenden"); input = Console.ReadLine(); if (input == "I") { recommenderType = "Itembased"; recommender = new GenericItemBasedRecommender(model, similarity); Console.WriteLine("Recommendertyp auf \"itembased\" geändert."); } else if (input == "U") { recommenderType = "Userbased"; recommender = new GenericUserBasedRecommender(model, neighborhood, similarity); Console.WriteLine("Recommendertyp auf \"userbased\" geändert."); } else if (input == "DE") { similarityType = "Cosine Similarity"; similarity = new UncenteredCosineSimilarity(model); Console.WriteLine("Similaritytyp auf \"Cosine Similarity\" geändert."); } else if (input == "PE") { similarityType = "Pearson Correlation Similarity"; similarity = new PearsonCorrelationSimilarity(model); Console.WriteLine("Similaritytyp auf \"Pearson Correlation Similarity\" geändert."); } else if (input == "N") { Console.WriteLine("Wie groß soll die Nachbarschaft sein?"); string neighborhoodSizeInput = Console.ReadLine(); if (int.TryParse(neighborhoodSizeInput, out int neighborhoodSizeParsed)) { neighborhoodSize = neighborhoodSizeParsed; neighborhood = new NearestNUserNeighborhood(neighborhoodSize, similarity, model); Console.WriteLine("Nachbarschaftsgröße auf " + neighborhoodSize + " geändert."); } else { Console.WriteLine("Error: Es wurde keine Zahl eingegeben."); Console.WriteLine("Die Nachbarschaftsgröße bleibt bei " + neighborhoodSize + "."); } } else if (input == "C") { Console.WriteLine("Wie groß soll die Nachbarschaft sein?"); string neighborhoodSizeInput = Console.ReadLine(); if (int.TryParse(neighborhoodSizeInput, out int neighborhoodSizeParsed)) { neighborhoodSize = neighborhoodSizeParsed; neighborhood = new NearestNUserNeighborhood(neighborhoodSize, similarity, model); Console.WriteLine("Nachbarschaftsgröße auf " + neighborhoodSize + " geändert."); } else { Console.WriteLine("Error: Es wurde keine Zahl eingegeben."); Console.WriteLine("Die Nachbarschaftsgröße bleibt bei " + neighborhoodSize + "."); } Console.WriteLine("Wieviele Filme sollen vorgeschlagen werden?"); string resultCountInput = Console.ReadLine(); if (int.TryParse(resultCountInput, out int resultCountParsed)) { resultCount = resultCountParsed; } else { Console.WriteLine("Error: Es wurde keine Zahl eingegeben."); Console.WriteLine("Die Anzahl der vorgeschlagenen Filme bleibt bei " + resultCount + "."); } foreach (int userId in userIdPredList) { Console.WriteLine("Vorgeschlagene Filme für User mit UserId " + userId); IList <IRecommendedItem> recommendedItems = recommender.Recommend(userId, resultCount); foreach (var recItem in recommendedItems) { Console.WriteLine("Item: " + recItem.GetItemID() + " (" + movies.First(x => x.movieId == recItem.GetItemID()).title + ") ===> " + recItem.GetValue()); } Console.WriteLine(); } // load movies movies = new List <MovieRecord>(); using (TextReader reader = File.OpenText(@"data/movies.csv")) { CsvReader csv = new CsvReader(reader); csv.Configuration.Delimiter = ","; csv.Configuration.MissingFieldFound = null; while (csv.Read()) { movies.Add(csv.GetRecord <MovieRecord>()); } } // load users users = new List <int>(); using (TextReader reader = File.OpenText(@"data/ratings.csv")) { CsvReader csv = new CsvReader(reader); csv.Configuration.Delimiter = ","; csv.Configuration.MissingFieldFound = null; while (csv.Read()) { if (int.TryParse(csv.GetField(0), out int id)) { if (!users.Contains(id)) { users.Add(id); } } } } model = new FileDataModel("data/ratings.csv", false, FileDataModel.DEFAULT_MIN_RELOAD_INTERVAL_MS, false); if (similarityType == "Cosine Similarity") { similarity = new UncenteredCosineSimilarity(model); } else { similarity = new PearsonCorrelationSimilarity(model); } neighborhood = new NearestNUserNeighborhood(neighborhoodSize, similarity, model); if (recommenderType == "Itembased") { recommender = new GenericItemBasedRecommender(model, similarity); } else { recommender = new GenericUserBasedRecommender(model, neighborhood, similarity); } } else if (input == "O") { int countPredUser = userIdPredList.Count; int countPredMovies = movieIdPredList.Count; Console.WriteLine("-----------------------------------------------"); Console.WriteLine("Recommender Typ: " + recommenderType); Console.WriteLine("Similarity Typ: " + similarityType); Console.WriteLine("Nachbarschaftsgröße: " + neighborhoodSize); Console.WriteLine("Anzahl Ergebnisse: " + resultCount); Console.WriteLine("Anzahl Benutzer: " + countPredUser); Console.WriteLine("Anzahl vorgeschlagene Filme: " + countPredMovies); Console.WriteLine("-----------------------------------------------"); } else if (input == "E") { Console.WriteLine("Wieviele Filme sollen vorgeschlagen werden?"); string resultCountInput = Console.ReadLine(); if (int.TryParse(resultCountInput, out int resultCountParsed)) { resultCount = resultCountParsed; } else { Console.WriteLine("Error: Es wurde keine Zahl eingegeben."); Console.WriteLine("Die Anzahl der vorgeschlagenen Filme bleibt bei " + resultCount + "."); } foreach (int userId in userIdPredList) { Console.WriteLine("Vorgeschlagene Filme für User mit UserId " + userId); IList <IRecommendedItem> recommendedItems = recommender.Recommend(userId, resultCount); foreach (var recItem in recommendedItems) { Console.WriteLine("Item: " + recItem.GetItemID() + " (" + movies.First(x => x.movieId == recItem.GetItemID()).title + ") ===> " + recItem.GetValue()); } Console.WriteLine(); } } else if (input == "P") { foreach (int userId in userIdPredList) { Console.WriteLine("Prediction für User mit Id" + userId + ":"); foreach (int movieId in movieIdPredList) { float predictionValue = recommender.EstimatePreference(userId, movieId); Console.WriteLine(movieId + " -> " + movies.First(x => x.movieId == movieId).title + " ===> " + predictionValue); } Console.WriteLine(); } } else if (input == "UADD") { Console.WriteLine("Welcher Benutzer (Id) soll zur Liste für Vorschläge hinzugefügt werden?"); string userIdInput = Console.ReadLine(); if (int.TryParse(userIdInput, out int userIdParsed)) { if (users.Contains(userIdParsed)) { userIdPredList.Add(userIdParsed); } else { Console.WriteLine("Error: UserId existiert nicht."); } } else { Console.WriteLine("Error: Es wurde keine Zahl eingegeben."); } } else if (input == "MADD") { Console.WriteLine("Welcher Film (Id) soll zur Liste für Vorschläge hinzugefügt werden?"); string movieIdInput = Console.ReadLine(); if (int.TryParse(movieIdInput, out int movieIdParsed)) { bool movieIdFound = false; foreach (MovieRecord movie in movies) { if (movie.movieId == movieIdParsed) { movieIdPredList.Add(movieIdParsed); movieIdFound = true; break; } } if (!movieIdFound) { Console.WriteLine("Error: movieId existiert nicht. Es wurde kein Film zur Liste hinzugefügt"); } } else { Console.WriteLine("Error: Es wurde keine Zahl eingegeben."); } } else if (input == "UCLEAR") { userIdPredList.Clear(); } else if (input == "MCLEAR") { movieIdPredList.Clear(); } } Console.WriteLine("Programm beendet"); Console.ReadLine(); }
public void testRescorer() { IDataModel dataModel = getDataModel( new long[] {1, 2, 3}, new Double?[][] { new double?[]{0.1, 0.2}, new double?[]{0.2, 0.3, 0.3, 0.6}, new double?[]{0.4, 0.4, 0.5, 0.9}, }); var similarities = new List<GenericItemSimilarity.ItemItemSimilarity>(); similarities.Add(new GenericItemSimilarity.ItemItemSimilarity(0, 1, 1.0)); similarities.Add(new GenericItemSimilarity.ItemItemSimilarity(0, 2, 0.5)); similarities.Add(new GenericItemSimilarity.ItemItemSimilarity(0, 3, 0.2)); similarities.Add(new GenericItemSimilarity.ItemItemSimilarity(1, 2, 0.7)); similarities.Add(new GenericItemSimilarity.ItemItemSimilarity(1, 3, 0.5)); similarities.Add(new GenericItemSimilarity.ItemItemSimilarity(2, 3, 0.9)); IItemSimilarity similarity = new GenericItemSimilarity(similarities); IRecommender recommender = new GenericItemBasedRecommender(dataModel, similarity); IList<IRecommendedItem> originalRecommended = recommender.Recommend(1, 2); IList<IRecommendedItem> rescoredRecommended = recommender.Recommend(1, 2, new ReversingRescorer<long>()); Assert.NotNull(originalRecommended); Assert.NotNull(rescoredRecommended); Assert.AreEqual(2, originalRecommended.Count); Assert.AreEqual(2, rescoredRecommended.Count); Assert.AreEqual(originalRecommended[0].GetItemID(), rescoredRecommended[1].GetItemID()); Assert.AreEqual(originalRecommended[1].GetItemID(), rescoredRecommended[0].GetItemID()); }
public void testHowMany() { IDataModel dataModel = getDataModel( new long[] {1, 2, 3, 4, 5}, new Double?[][] { new double?[]{0.1, 0.2}, new double?[]{0.2, 0.3, 0.3, 0.6}, new double?[]{0.4, 0.4, 0.5, 0.9}, new double?[]{0.1, 0.4, 0.5, 0.8, 0.9, 1.0}, new double?[]{0.2, 0.3, 0.6, 0.7, 0.1, 0.2}, }); var similarities = new List<GenericItemSimilarity.ItemItemSimilarity>(); for (int i = 0; i < 6; i++) { for (int j = i + 1; j < 6; j++) { similarities.Add( new GenericItemSimilarity.ItemItemSimilarity(i, j, 1.0 / (1.0 + i + j))); } } IItemSimilarity similarity = new GenericItemSimilarity(similarities); IRecommender recommender = new GenericItemBasedRecommender(dataModel, similarity); IList<IRecommendedItem> fewRecommended = recommender.Recommend(1, 2); IList<IRecommendedItem> moreRecommended = recommender.Recommend(1, 4); for (int i = 0; i < fewRecommended.Count; i++) { Assert.AreEqual(fewRecommended[i].GetItemID(), moreRecommended[i].GetItemID()); } recommender.Refresh(null); for (int i = 0; i < fewRecommended.Count; i++) { Assert.AreEqual(fewRecommended[i].GetItemID(), moreRecommended[i].GetItemID()); } }