Exemplo n.º 1
0
        public override double GetEvaluation(IDictionary <User, ICollection <Preference> > testUserPrefs,
                                             Recommender recommender)
        {
            RunningAverage average = new FullRunningAverage();

            foreach (KeyValuePair <User, ICollection <Preference> > entry in testUserPrefs)
            {
                foreach (Preference realPref in entry.Value)
                {
                    User testUser = entry.Key;
                    try
                    {
                        double estimatedPreference =
                            recommender.EstimatePreference(testUser.ID, realPref.Item.ID);
                        if (!double.IsNaN(estimatedPreference))
                        {
                            double diff = realPref.Value - estimatedPreference;
                            average.AddDatum(diff * diff);
                        }
                    }
                    catch (NoSuchElementException nsee)
                    {
                        // It's possible that an item exists in the test data but not training data in which case
                        // NSEE will be thrown. Just ignore it and move on.
                        log.Info("Element exists in test data but not training data: " + testUser.ID, nsee);
                    }
                }
            }
            return(Math.Sqrt(average.Average));
        }
        public override void SetPreference(long userID, long itemID, float value)
        {
            IDataModel dataModel = GetDataModel();
            double     prefDelta;

            try {
                float?oldPref = dataModel.GetPreferenceValue(userID, itemID);
                prefDelta = !oldPref.HasValue ? value : value - oldPref.Value;
            } catch (NoSuchUserException nsee) {
                prefDelta = value;
            }
            base.SetPreference(userID, itemID, value);
            lock (this) {
                //buildAveragesLock.writeLock().lock();
                IRunningAverage average = itemAverages.Get(itemID);
                if (average == null)
                {
                    IRunningAverage newAverage = new FullRunningAverage();
                    newAverage.AddDatum(prefDelta);
                    itemAverages.Put(itemID, newAverage);
                }
                else
                {
                    average.ChangeDatum(prefDelta);
                }
            }
            //finally {
            //buildAveragesLock.writeLock().unlock();
            //}
        }
 private void buildAverageDiffs()
 {
     lock (this) {
         //buildAveragesLock.writeLock().lock();
         IDataModel dataModel = GetDataModel();
         var        it        = dataModel.GetUserIDs();
         while (it.MoveNext())
         {
             IPreferenceArray prefs = dataModel.GetPreferencesFromUser(it.Current);
             int size = prefs.Length();
             for (int i = 0; i < size; i++)
             {
                 long            itemID  = prefs.GetItemID(i);
                 IRunningAverage average = itemAverages.Get(itemID);
                 if (average == null)
                 {
                     average = new FullRunningAverage();
                     itemAverages.Put(itemID, average);
                 }
                 average.AddDatum(prefs.GetValue(i));
             }
         }
     }
     //finally {
     //buildAveragesLock.writeLock().unlock();
     //}
 }
Exemplo n.º 4
0
            public double estimate(long itemID)
            {
                RunningAverage average = new FullRunningAverage();

                double[] numArray = this.similarity.itemSimilarities(itemID, this.toItemIDs);
                for (int i = 0; i < this.toItemIDs.Length; i++)
                {
                    long num2 = this.toItemIDs[i];
                    Tuple <long, long> thing = new Tuple <long, long>(num2, itemID);
                    if ((this.rescorer == null) || !this.rescorer.isFiltered(thing))
                    {
                        double originalScore = numArray[i];
                        if (this.rescorer != null)
                        {
                            originalScore = this.rescorer.rescore(thing, originalScore);
                        }
                        if (!(!this.excludeItemIfNotSimilarToAll && double.IsNaN(originalScore)))
                        {
                            average.addDatum(originalScore);
                        }
                    }
                }
                double num4 = average.getAverage();

                return((num4 == 0.0) ? double.NaN : num4);
            }
Exemplo n.º 5
0
            public double Estimate(long itemID)
            {
                IRunningAverage average = new FullRunningAverage();

                double[] similarities = similarity.ItemSimilarities(itemID, toItemIDs);
                for (int i = 0; i < toItemIDs.Length; i++)
                {
                    long toItemID           = toItemIDs[i];
                    Tuple <long, long> pair = new Tuple <long, long>(toItemID, itemID);
                    if (rescorer != null && rescorer.IsFiltered(pair))
                    {
                        continue;
                    }
                    double estimate = similarities[i];
                    if (rescorer != null)
                    {
                        estimate = rescorer.Rescore(pair, estimate);
                    }
                    if (excludeItemIfNotSimilarToAll || !Double.IsNaN(estimate))
                    {
                        average.AddDatum(estimate);
                    }
                }
                double averageEstimate = average.GetAverage();

                return(averageEstimate == 0 ? Double.NaN : averageEstimate);
            }
Exemplo n.º 6
0
        public override void setPreference(long userID, long itemID, float value)
        {
            double    num;
            DataModel model = this.getDataModel();

            try
            {
                float?nullable = model.getPreferenceValue(userID, itemID);
                num = !nullable.HasValue ? ((double)value) : ((double)(value - nullable.Value));
            }
            catch (NoSuchUserException)
            {
                num = value;
            }
            base.setPreference(userID, itemID, value);
            lock (this)
            {
                RunningAverage average = this.itemAverages.get(itemID);
                if (average == null)
                {
                    RunningAverage average2 = new FullRunningAverage();
                    average2.addDatum(num);
                    this.itemAverages.put(itemID, average2);
                }
                else
                {
                    average.changeDatum(num);
                }
            }
        }
        public void toyExample()
        {
            SVDRecommender svdRecommender = new SVDRecommender(dataModel, factorizer);

            /// a hold out test would be better, but this is just a toy example so we only check that the
            /// factorization is close to the original matrix
            IRunningAverage avg     = new FullRunningAverage();
            var             userIDs = dataModel.GetUserIDs();

            while (userIDs.MoveNext())
            {
                long userID = userIDs.Current;
                foreach (IPreference pref in dataModel.GetPreferencesFromUser(userID))
                {
                    double rating   = pref.GetValue();
                    double estimate = svdRecommender.EstimatePreference(userID, pref.GetItemID());
                    double err      = rating - estimate;
                    avg.AddDatum(err * err);
                }
            }

            double rmse = Math.Sqrt(avg.GetAverage());

            Assert.True(rmse < 0.2);
        }
Exemplo n.º 8
0
        public void testRecommenderWithSyntheticData()
        {
            setUpSyntheticData();

            factorizer     = new ParallelSGDFactorizer(dataModel, rank, lambda, numIterations, 0.01, 1, 0, 0);
            svdRecommender = new SVDRecommender(dataModel, factorizer);

            /// a hold out test would be better, but this is just a toy example so we only check that the
            /// factorization is close to the original matrix
            IRunningAverage avg     = new FullRunningAverage();
            var             userIDs = dataModel.GetUserIDs();

            while (userIDs.MoveNext())
            {
                long userID = userIDs.Current;
                foreach (IPreference pref in dataModel.GetPreferencesFromUser(userID))
                {
                    double rating   = pref.GetValue();
                    double estimate = svdRecommender.EstimatePreference(userID, pref.GetItemID());
                    double err      = rating - estimate;
                    avg.AddDatum(err * err);
                }
            }

            double rmse = Math.Sqrt(avg.GetAverage());

            logger.Info("rmse: " + rmse);
            Assert.True(rmse < 0.2);
        }
Exemplo n.º 9
0
        private void BuildAverageDiffs()
        {
            buildAveragesLock.AcquireWriterLock(Constants.INFINITE_TIMEOUT);
            try
            {
                foreach (User user in this.DataModel.GetUsers())
                {
                    Preference[] prefs = user.GetPreferencesAsArray();
                    foreach (Preference pref in prefs)
                    {
                        Object itemID = pref.Item.ID;

                        RunningAverage average = null;
                        if (!itemAverages.TryGetValue(itemID, out average))
                        {
                            average = new FullRunningAverage();
                            itemAverages.Add(itemID, average);
                        }
                        average.AddDatum(pref.Value);
                    }
                }
                averagesBuilt = true;
            }
            finally
            {
                buildAveragesLock.ReleaseWriterLock();
            }
        }
Exemplo n.º 10
0
        private long processLine(String line, long averageCount)
        {
            if (string.IsNullOrEmpty(line) || line[0] == COMMENT_CHAR)
            {
                return(averageCount);
            }

            String[] tokens = SEPARATOR.Split(line);
            //Preconditions.checkArgument(tokens.length >= 3 && tokens.length != 5, "Bad line: %s", line);

            long   itemID1 = long.Parse(tokens[0]);
            long   itemID2 = long.Parse(tokens[1]);
            double diff    = double.Parse(tokens[2]);
            int    count   = tokens.Length >= 4 ? int.Parse(tokens[3]) : 1;
            bool   hasMkSk = tokens.Length >= 5;

            if (itemID1 > itemID2)
            {
                long temp = itemID1;
                itemID1 = itemID2;
                itemID2 = temp;
            }

            FastByIDMap <RunningAverage> level1Map = averageDiffs.get(itemID1);

            if (level1Map == null)
            {
                level1Map = new FastByIDMap <RunningAverage>();
                averageDiffs.put(itemID1, level1Map);
            }
            RunningAverage average = level1Map.get(itemID2);

            if (average != null)
            {
                throw new Exception("Duplicated line for item-item pair " + itemID1 + " / " + itemID2);
            }
            if (averageCount < maxEntries)
            {
                if (hasMkSk)
                {
                    double mk = Double.Parse(tokens[4]);
                    double sk = Double.Parse(tokens[5]);
                    average = new FullRunningAverageAndStdDev(count, diff, mk, sk);
                }
                else
                {
                    average = new FullRunningAverage(count, diff);
                }
                level1Map.put(itemID2, average);
                averageCount++;
            }

            allRecommendableItemIDs.add(itemID1);
            allRecommendableItemIDs.add(itemID2);

            return(averageCount);
        }
Exemplo n.º 11
0
            public double averateRating(long itemID)
            {
                PreferenceArray array   = this.dataModel.getPreferencesForItem(itemID);
                RunningAverage  average = new FullRunningAverage();

                foreach (Preference preference in array)
                {
                    average.addDatum((double)preference.getValue());
                }
                return(average.getAverage());
            }
Exemplo n.º 12
0
        private static void addDatumAndCreateIfNeeded(long itemID, float value, FastByIDMap <RunningAverage> averages)
        {
            RunningAverage average = averages.get(itemID);

            if (average == null)
            {
                average = new FullRunningAverage();
                averages.put(itemID, average);
            }
            average.addDatum((double)value);
        }
Exemplo n.º 13
0
        private static void addDatumAndCreateIfNeeded(long itemID, float value, FastByIDMap <IRunningAverage> averages)
        {
            IRunningAverage itemAverage = averages.Get(itemID);

            if (itemAverage == null)
            {
                itemAverage = new FullRunningAverage();
                averages.Put(itemID, itemAverage);
            }
            itemAverage.AddDatum(value);
        }
Exemplo n.º 14
0
            public double averateRating(long itemID)
            {
                IPreferenceArray prefs = dataModel.GetPreferencesForItem(itemID);
                IRunningAverage  avg   = new FullRunningAverage();

                foreach (IPreference pref in prefs)
                {
                    avg.AddDatum(pref.GetValue());
                }
                return(avg.GetAverage());
            }
Exemplo n.º 15
0
        public void toyExampleImplicit()
        {
            var observations = new double[4, 4] {
                { 5.0, 5.0, 2.0, 0 },
                { 2.0, 0, 3.0, 5.0 },
                { 0, 5.0, 0, 3.0 },
                { 3.0, 0, 0, 5.0 }
            };

            var preferences = new double[4, 4] {
                { 1.0, 1.0, 1.0, 0 },
                { 1.0, 0, 1.0, 1.0 },
                { 0, 1.0, 0, 1.0 },
                { 1.0, 0, 0, 1.0 }
            };

            double alpha = 20;

            ALSWRFactorizer factorizer = new ALSWRFactorizer(dataModel, 3, 0.065, 5, true, alpha);

            SVDRecommender svdRecommender = new SVDRecommender(dataModel, factorizer);

            IRunningAverage avg = new FullRunningAverage();

            for (int sliceIdx = 0; sliceIdx < preferences.GetLength(0); sliceIdx++)
            {
                var slice = MatrixUtil.viewRow(preferences, sliceIdx);
                for (var eIndex = 0; eIndex < slice.Length; eIndex++)
                {
                    var  e      = slice[eIndex];
                    long userID = sliceIdx + 1;
                    long itemID = eIndex + 1;

                    if (!Double.IsNaN(e))
                    {
                        double pref     = e;
                        double estimate = svdRecommender.EstimatePreference(userID, itemID);

                        double confidence = 1 + alpha * observations[sliceIdx, eIndex];
                        double err        = confidence * (pref - estimate) * (pref - estimate);
                        avg.AddDatum(err);
                        Console.WriteLine("Comparing preference of user [{0}] towards item [{1}], was [{2}] with confidence [{3}] "
                                          + "estimate is [{4}]", sliceIdx, eIndex, pref, confidence, estimate);
                    }
                }
            }
            double rmse = Math.Sqrt(avg.GetAverage());

            Console.WriteLine("RMSE: {0}", rmse);

            Assert.True(rmse < 0.4);
        }
Exemplo n.º 16
0
        private static void AddDatumAndCrateIfNeeded(Object itemID,
                                                     double value,
                                                     IDictionary <Object, RunningAverage> averages)
        {
            RunningAverage itemAverage;

            if (!averages.TryGetValue(itemID, out itemAverage))
            {
                itemAverage = new FullRunningAverage();
                averages.Add(itemID, itemAverage);
            }
            itemAverage.AddDatum(value);
        }
Exemplo n.º 17
0
        private double getAveragePreference()
        {
            RunningAverage     average    = new FullRunningAverage();
            IEnumerator <long> enumerator = this.dataModel.getUserIDs();

            while (enumerator.MoveNext())
            {
                foreach (Preference preference in this.dataModel.getPreferencesFromUser(enumerator.Current))
                {
                    average.addDatum((double)preference.getValue());
                }
            }
            return(average.getAverage());
        }
Exemplo n.º 18
0
            public double Estimate(Item item)
            {
                RunningAverage average = new FullRunningAverage();

                foreach (User user in cluster)
                {
                    Preference pref = user.GetPreferenceFor(item.ID);
                    if (pref != null)
                    {
                        average.AddDatum(pref.Value);
                    }
                }
                return(average.Average);
            }
Exemplo n.º 19
0
        double getAveragePreference()
        {
            IRunningAverage average = new FullRunningAverage();
            var             it      = dataModel.GetUserIDs();

            while (it.MoveNext())
            {
                foreach (IPreference pref in dataModel.GetPreferencesFromUser(it.Current))
                {
                    average.AddDatum(pref.GetValue());
                }
            }
            return(average.GetAverage());
        }
Exemplo n.º 20
0
        /**
         * {@inheritDoc}
         */
        public override void SetPreference(Object userID, Object itemID, double value)
        {
            DataModel dataModel = this.DataModel;
            double    prefDelta;

            try
            {
                User       theUser = dataModel.GetUser(userID);
                Preference oldPref = theUser.GetPreferenceFor(itemID);
                prefDelta = oldPref == null ? value : value - oldPref.Value;
            }
            catch (NoSuchElementException)
            {
                prefDelta = value;
            }
            base.SetPreference(userID, itemID, value);
            buildAveragesLock.AcquireWriterLock(Constants.INFINITE_TIMEOUT);
            try
            {
                RunningAverage itemAverage;
                if (!itemAverages.TryGetValue(itemID, out itemAverage) || itemAverage == null)
                {
                    RunningAverage newItemAverage = new FullRunningAverage();
                    newItemAverage.AddDatum(prefDelta);
                    itemAverages.Add(itemID, newItemAverage);
                }
                else
                {
                    itemAverage.ChangeDatum(prefDelta);
                }

                RunningAverage userAverage;

                if (!userAverages.TryGetValue(userID, out userAverage) || userAverage == null)
                {
                    RunningAverage newUserAverage = new FullRunningAverage();
                    newUserAverage.AddDatum(prefDelta);
                    userAverages.Add(userID, newUserAverage);
                }
                else
                {
                    userAverage.ChangeDatum(prefDelta);
                }
                overallAveragePrefValue.ChangeDatum(prefDelta);
            } finally {
                buildAveragesLock.ReleaseWriterLock();
            }
        }
Exemplo n.º 21
0
            public double estimate(long itemID)
            {
                DataModel      dataModel = this.re.getDataModel();
                RunningAverage average   = new FullRunningAverage();
                var            it        = cluster.GetEnumerator();

                while (it.MoveNext())
                {
                    float?pref = dataModel.getPreferenceValue(it.Current, itemID);
                    if (pref != null)
                    {
                        average.addDatum(pref.Value);
                    }
                }
                return(average.getAverage());
            }
Exemplo n.º 22
0
            public Double GetValue(User key)
            {
                RunningAverage average = new FullRunningAverage();

                Preference[] prefs = key.GetPreferencesAsArray();
                if (prefs.Length == 0)
                {
                    return(0.0);
                }

                foreach (Preference pref in prefs)
                {
                    average.AddDatum(pref.Value);
                }
                return(average.Average);
            }
Exemplo n.º 23
0
            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 float Get(long key)
            {
                IPreferenceArray prefs = inf.dataModel.GetPreferencesFromUser(key);
                int size = prefs.Length();

                if (size == 0)
                {
                    return(ZERO);
                }
                IRunningAverage average = new FullRunningAverage();

                for (int i = 0; i < size; i++)
                {
                    average.AddDatum(prefs.GetValue(i));
                }
                return((float)average.GetAverage());
            }
Exemplo n.º 25
0
            public float get(long key)
            {
                PreferenceArray array = this.inf.dataModel.getPreferencesFromUser(key);
                int             num   = array.length();

                if (num == 0)
                {
                    return(AveragingPreferenceInferrer.ZERO);
                }
                RunningAverage average = new FullRunningAverage();

                for (int i = 0; i < num; i++)
                {
                    average.addDatum((double)array.getValue(i));
                }
                return((float)average.getAverage());
            }
Exemplo n.º 26
0
        public override void SetPreference(Object userID, Object itemID, double value)
        {
            double prefDelta;

            try
            {
                User       theUser = this.DataModel.GetUser(userID);
                Preference oldPref = theUser.GetPreferenceFor(itemID);
                prefDelta = oldPref == null ? value : value - oldPref.Value;
            }
            catch
            {
                prefDelta = value;
            }
            base.SetPreference(userID, itemID, value);

            buildAveragesLock.AcquireWriterLock(Constants.INFINITE_TIMEOUT);
            try
            {
                RunningAverage average = null;
                if (!itemAverages.TryGetValue(itemID, out average))
                {
                    RunningAverage newAverage = new FullRunningAverage();
                    newAverage.AddDatum(prefDelta);
                    itemAverages.Add(itemID, newAverage);
                }
                else
                {
                    average.ChangeDatum(prefDelta);
                }
            }
            finally
            {
                buildAveragesLock.ReleaseWriterLock();
            }
        }
Exemplo n.º 27
0
 private void buildAverageDiffs()
 {
     lock (this)
     {
         DataModel          model      = this.getDataModel();
         IEnumerator <long> enumerator = model.getUserIDs();
         while (enumerator.MoveNext())
         {
             PreferenceArray array = model.getPreferencesFromUser(enumerator.Current);
             int             num   = array.length();
             for (int i = 0; i < num; i++)
             {
                 long           key     = array.getItemID(i);
                 RunningAverage average = this.itemAverages.get(key);
                 if (average == null)
                 {
                     average = new FullRunningAverage();
                     this.itemAverages.put(key, average);
                 }
                 average.addDatum((double)array.getValue(i));
             }
         }
     }
 }
Exemplo n.º 28
0
        public IRStatistics Evaluate(IRecommenderBuilder recommenderBuilder,
                                     IDataModelBuilder dataModelBuilder,
                                     IDataModel dataModel,
                                     IDRescorer rescorer,
                                     int at,
                                     double relevanceThreshold,
                                     double evaluationPercentage)
        {
            //Preconditions.checkArgument(recommenderBuilder != null, "recommenderBuilder is null");
            //Preconditions.checkArgument(dataModel != null, "dataModel is null");
            //Preconditions.checkArgument(at >= 1, "at must be at least 1");
            //Preconditions.checkArgument(evaluationPercentage > 0.0 && evaluationPercentage <= 1.0,
            //    "Invalid evaluationPercentage: " + evaluationPercentage + ". Must be: 0.0 < evaluationPercentage <= 1.0");

            int             numItems  = dataModel.GetNumItems();
            IRunningAverage precision = new FullRunningAverage();
            IRunningAverage recall    = new FullRunningAverage();
            IRunningAverage fallOut   = new FullRunningAverage();
            IRunningAverage nDCG      = new FullRunningAverage();
            int             numUsersRecommendedFor      = 0;
            int             numUsersWithRecommendations = 0;

            var it = dataModel.GetUserIDs();

            while (it.MoveNext())
            {
                long userID = it.Current;

                if (random.nextDouble() >= evaluationPercentage)
                {
                    // Skipped
                    continue;
                }

                var stopWatch = new System.Diagnostics.Stopwatch();
                stopWatch.Start();

                IPreferenceArray prefs = dataModel.GetPreferencesFromUser(userID);

                // List some most-preferred items that would count as (most) "relevant" results
                double    theRelevanceThreshold = Double.IsNaN(relevanceThreshold) ? computeThreshold(prefs) : relevanceThreshold;
                FastIDSet relevantItemIDs       = dataSplitter.GetRelevantItemsIDs(userID, at, theRelevanceThreshold, dataModel);

                int numRelevantItems = relevantItemIDs.Count();
                if (numRelevantItems <= 0)
                {
                    continue;
                }

                FastByIDMap <IPreferenceArray> trainingUsers = new FastByIDMap <IPreferenceArray>(dataModel.GetNumUsers());
                var it2 = dataModel.GetUserIDs();
                while (it2.MoveNext())
                {
                    dataSplitter.ProcessOtherUser(userID, relevantItemIDs, trainingUsers, it2.Current, dataModel);
                }

                IDataModel trainingModel = dataModelBuilder == null ? new GenericDataModel(trainingUsers)
          : dataModelBuilder.BuildDataModel(trainingUsers);
                try {
                    trainingModel.GetPreferencesFromUser(userID);
                } catch (NoSuchUserException nsee) {
                    continue; // Oops we excluded all prefs for the user -- just move on
                }

                int size = numRelevantItems + trainingModel.GetItemIDsFromUser(userID).Count();
                if (size < 2 * at)
                {
                    // Really not enough prefs to meaningfully evaluate this user
                    continue;
                }

                IRecommender recommender = recommenderBuilder.BuildRecommender(trainingModel);

                int intersectionSize = 0;
                var recommendedItems = recommender.Recommend(userID, at, rescorer);
                foreach (IRecommendedItem recommendedItem in recommendedItems)
                {
                    if (relevantItemIDs.Contains(recommendedItem.GetItemID()))
                    {
                        intersectionSize++;
                    }
                }

                int numRecommendedItems = recommendedItems.Count;

                // Precision
                if (numRecommendedItems > 0)
                {
                    precision.AddDatum((double)intersectionSize / (double)numRecommendedItems);
                }

                // Recall
                recall.AddDatum((double)intersectionSize / (double)numRelevantItems);

                // Fall-out
                if (numRelevantItems < size)
                {
                    fallOut.AddDatum((double)(numRecommendedItems - intersectionSize)
                                     / (double)(numItems - numRelevantItems));
                }

                // nDCG
                // In computing, assume relevant IDs have relevance 1 and others 0
                double cumulativeGain = 0.0;
                double idealizedGain  = 0.0;
                for (int i = 0; i < numRecommendedItems; i++)
                {
                    IRecommendedItem item     = recommendedItems[i];
                    double           discount = 1.0 / log2(i + 2.0); // Classical formulation says log(i+1), but i is 0-based here
                    if (relevantItemIDs.Contains(item.GetItemID()))
                    {
                        cumulativeGain += discount;
                    }
                    // otherwise we're multiplying discount by relevance 0 so it doesn't do anything

                    // Ideally results would be ordered with all relevant ones first, so this theoretical
                    // ideal list starts with number of relevant items equal to the total number of relevant items
                    if (i < numRelevantItems)
                    {
                        idealizedGain += discount;
                    }
                }
                if (idealizedGain > 0.0)
                {
                    nDCG.AddDatum(cumulativeGain / idealizedGain);
                }

                // Reach
                numUsersRecommendedFor++;
                if (numRecommendedItems > 0)
                {
                    numUsersWithRecommendations++;
                }

                stopWatch.Stop();

                log.Info("Evaluated with user {} in {}ms", userID, stopWatch.ElapsedMilliseconds);
                log.Info("Precision/recall/fall-out/nDCG/reach: {} / {} / {} / {} / {}",
                         precision.GetAverage(), recall.GetAverage(), fallOut.GetAverage(), nDCG.GetAverage(),
                         (double)numUsersWithRecommendations / (double)numUsersRecommendedFor);
            }

            return(new IRStatisticsImpl(
                       precision.GetAverage(),
                       recall.GetAverage(),
                       fallOut.GetAverage(),
                       nDCG.GetAverage(),
                       (double)numUsersWithRecommendations / (double)numUsersRecommendedFor));
        }
        public IRStatistics Evaluate(RecommenderBuilder recommenderBuilder,
                                     DataModel dataModel,
                                     int at,
                                     double relevanceThreshold,
                                     double evaluationPercentage)
        {
            if (recommenderBuilder == null)
            {
                throw new ArgumentNullException("recommenderBuilder is null");
            }
            if (dataModel == null)
            {
                throw new ArgumentNullException("dataModel is null");
            }
            if (at < 1)
            {
                throw new ArgumentException("at must be at least 1");
            }
            if (double.IsNaN(evaluationPercentage) || evaluationPercentage <= 0.0 || evaluationPercentage > 1.0)
            {
                throw new ArgumentException("Invalid evaluationPercentage: " + evaluationPercentage);
            }
            if (double.IsNaN(relevanceThreshold))
            {
                throw new ArgumentException("Invalid relevanceThreshold: " + evaluationPercentage);
            }

            RunningAverage precision = new FullRunningAverage();
            RunningAverage recall    = new FullRunningAverage();

            foreach (User user in dataModel.GetUsers())
            {
                Object id = user.ID;
                if (random.NextDouble() < evaluationPercentage)
                {
                    ICollection <Item> relevantItems = new HashedSet <Item>(/* at */);
                    Preference[]       prefs         = user.GetPreferencesAsArray();

                    foreach (Preference pref in prefs)
                    {
                        if (pref.Value >= relevanceThreshold)
                        {
                            relevantItems.Add(pref.Item);
                        }
                    }
                    int numRelevantItems = relevantItems.Count;
                    if (numRelevantItems > 0)
                    {
                        ICollection <User> trainingUsers = new List <User>(dataModel.GetNumUsers());
                        foreach (User user2 in dataModel.GetUsers())
                        {
                            if (id.Equals(user2.ID))
                            {
                                ICollection <Preference> trainingPrefs = new List <Preference>();
                                prefs = user2.GetPreferencesAsArray();
                                foreach (Preference pref in prefs)
                                {
                                    if (!relevantItems.Contains(pref.Item))
                                    {
                                        trainingPrefs.Add(pref);
                                    }
                                }
                                if (trainingPrefs.Count > 0)
                                {
                                    User trainingUser = new GenericUser <String>(id.ToString(), trainingPrefs);
                                    trainingUsers.Add(trainingUser);
                                }
                            }
                            else
                            {
                                trainingUsers.Add(user2);
                            }
                        }
                        DataModel   trainingModel = new GenericDataModel(trainingUsers);
                        Recommender recommender   = recommenderBuilder.BuildRecommender(trainingModel);

                        try
                        {
                            trainingModel.GetUser(id);
                        }
                        catch (NoSuchElementException)
                        {
                            continue;                             // Oops we excluded all prefs for the user -- just move on
                        }

                        int intersectionSize = 0;
                        foreach (RecommendedItem recommendedItem in recommender.Recommend(id, at))
                        {
                            if (relevantItems.Contains(recommendedItem.Item))
                            {
                                intersectionSize++;
                            }
                        }
                        precision.AddDatum((double)intersectionSize / (double)at);
                        recall.AddDatum((double)intersectionSize / (double)numRelevantItems);
                    }
                }
            }

            return(new IRStatisticsImpl(precision.Average, recall.Average));
        }
        public IRStatistics evaluate(RecommenderBuilder recommenderBuilder, DataModelBuilder dataModelBuilder, DataModel dataModel, IDRescorer rescorer, int at, double relevanceThreshold, double evaluationPercentage)
        {
            int                num        = dataModel.getNumItems();
            RunningAverage     average    = new FullRunningAverage();
            RunningAverage     average2   = new FullRunningAverage();
            RunningAverage     average3   = new FullRunningAverage();
            RunningAverage     average4   = new FullRunningAverage();
            int                num2       = 0;
            int                num3       = 0;
            IEnumerator <long> enumerator = dataModel.getUserIDs();

            while (enumerator.MoveNext())
            {
                long current = enumerator.Current;
                if (this.random.nextDouble() < evaluationPercentage)
                {
                    Stopwatch stopwatch = new Stopwatch();
                    stopwatch.Start();
                    PreferenceArray prefs           = dataModel.getPreferencesFromUser(current);
                    double          num5            = double.IsNaN(relevanceThreshold) ? computeThreshold(prefs) : relevanceThreshold;
                    FastIDSet       relevantItemIDs = this.dataSplitter.getRelevantItemsIDs(current, at, num5, dataModel);
                    int             num6            = relevantItemIDs.size();
                    if (num6 > 0)
                    {
                        FastByIDMap <PreferenceArray> trainingUsers = new FastByIDMap <PreferenceArray>(dataModel.getNumUsers());
                        IEnumerator <long>            enumerator2   = dataModel.getUserIDs();
                        while (enumerator2.MoveNext())
                        {
                            this.dataSplitter.processOtherUser(current, relevantItemIDs, trainingUsers, enumerator2.Current, dataModel);
                        }
                        DataModel model = (dataModelBuilder == null) ? new GenericDataModel(trainingUsers) : dataModelBuilder.buildDataModel(trainingUsers);
                        try
                        {
                            model.getPreferencesFromUser(current);
                        }
                        catch (NoSuchUserException)
                        {
                            continue;
                        }
                        int num7 = num6 + model.getItemIDsFromUser(current).size();
                        if (num7 >= (2 * at))
                        {
                            Recommender            recommender = recommenderBuilder.buildRecommender(model);
                            int                    num8        = 0;
                            List <RecommendedItem> list        = recommender.recommend(current, at, rescorer);
                            foreach (RecommendedItem item in list)
                            {
                                if (relevantItemIDs.contains(item.getItemID()))
                                {
                                    num8++;
                                }
                            }
                            int count = list.Count;
                            if (count > 0)
                            {
                                average.addDatum(((double)num8) / ((double)count));
                            }
                            average2.addDatum(((double)num8) / ((double)num6));
                            if (num6 < num7)
                            {
                                average3.addDatum(((double)(count - num8)) / ((double)(num - num6)));
                            }
                            double num10 = 0.0;
                            double num11 = 0.0;
                            for (int i = 0; i < count; i++)
                            {
                                RecommendedItem item2 = list[i];
                                double          num13 = 1.0 / log2(i + 2.0);
                                if (relevantItemIDs.contains(item2.getItemID()))
                                {
                                    num10 += num13;
                                }
                                if (i < num6)
                                {
                                    num11 += num13;
                                }
                            }
                            if (num11 > 0.0)
                            {
                                average4.addDatum(num10 / num11);
                            }
                            num2++;
                            if (count > 0)
                            {
                                num3++;
                            }
                            stopwatch.Stop();
                            log.info("Evaluated with user {} in {}ms", new object[] { current, stopwatch.ElapsedMilliseconds });
                            log.info("Precision/recall/fall-out/nDCG/reach: {} / {} / {} / {} / {}", new object[] { average.getAverage(), average2.getAverage(), average3.getAverage(), average4.getAverage(), ((double)num3) / ((double)num2) });
                        }
                    }
                }
            }
            return(new IRStatisticsImpl(average.getAverage(), average2.getAverage(), average3.getAverage(), average4.getAverage(), ((double)num3) / ((double)num2)));
        }