예제 #1
0
        /// <summary>
        /// Gets a cached prediction engine or creates a new one if not cached
        /// </summary>
        private BatchPredictionEngine <SarUsageEvent, SarScoreResult> GetOrCreateBatchPredictionEngine(
            IList <SarUsageEvent> usageItems, SarScoringArguments sarScoringArguments)
        {
            var arguments = new RecommenderScorerTransform.Arguments
            {
                // round the recommendations count to optimize engine cache
                recommendationCount = GetRoundedNumberOfResults(sarScoringArguments.RecommendationCount),
                includeHistory      = sarScoringArguments.IncludeHistory
            };

            // create a data column mapping
            var dataColumnMapping = new Dictionary <RoleMappedSchema.ColumnRole, string>
            {
                { new RoleMappedSchema.ColumnRole("Item"), "Item" },
                { new RoleMappedSchema.ColumnRole("User"), "user" }
            };

            string weightColumn = null;

            if (sarScoringArguments.ReferenceDate.HasValue)
            {
                // rounding the reference date to the beginning of next day to optimize engine cache
                DateTime referenceDate = sarScoringArguments.ReferenceDate.Value.Date + TimeSpan.FromDays(1);
                arguments.referenceDate = referenceDate.ToString("s");
                if (sarScoringArguments.Decay.HasValue)
                {
                    arguments.decay = sarScoringArguments.Decay.Value.TotalDays;
                }

                dataColumnMapping.Add(new RoleMappedSchema.ColumnRole("Date"), "date");
                weightColumn = "weight";
            }

            // create an engine cache key
            string cacheKey = $"{arguments.recommendationCount}|{arguments.includeHistory}|{arguments.referenceDate}|{arguments.decay}";

            _tracer.TraceVerbose("Trying to find the engine in the cache");
            var engine = _enginesCache.Get(cacheKey) as BatchPredictionEngine <SarUsageEvent, SarScoreResult>;

            if (engine == null)
            {
                _tracer.TraceInformation("Engine is not cached - creating a new engine");
                IDataView             pipeline            = _environment.CreateDataView(usageItems, _usageDataSchema);
                RoleMappedData        usageDataMappedData = _environment.CreateExamples(pipeline, null, weight: weightColumn, custom: dataColumnMapping);
                ISchemaBindableMapper mapper      = RecommenderScorerTransform.Create(_environment, arguments, _recommender);
                ISchemaBoundMapper    boundMapper = mapper.Bind(_environment, usageDataMappedData.Schema);
                IDataScorerTransform  scorer      = RecommenderScorerTransform.Create(
                    _environment, arguments, pipeline, boundMapper, null);
                engine = _environment.CreateBatchPredictionEngine <SarUsageEvent, SarScoreResult>(scorer, false, _usageDataSchema);

                bool result = _enginesCache.Add(cacheKey, engine, new CacheItemPolicy {
                    SlidingExpiration = TimeSpan.FromDays(1)
                });
                _tracer.TraceVerbose($"Addition of engine to the cache resulted with '{result}'");
            }

            return(engine);
        }
예제 #2
0
        /// <summary>
        /// Scores the input usage items.
        /// </summary>
        /// <param name="usageItems">The items to score</param>
        /// <param name="scoringArguments">The scoring arguments</param>
        /// <returns></returns>
        public IEnumerable <SarScoreResult> ScoreUsageItems(IList <SarUsageEvent> usageItems, SarScoringArguments scoringArguments)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(typeof(SarScorer).FullName);
            }

            if (usageItems == null)
            {
                throw new ArgumentNullException(nameof(usageItems));
            }

            if (scoringArguments == null)
            {
                throw new ArgumentNullException(nameof(scoringArguments));
            }

            _tracer.TraceVerbose("Getting or creating the prediction engine");
            BatchPredictionEngine <SarUsageEvent, SarScoreResult> engine =
                GetOrCreateBatchPredictionEngine(usageItems, scoringArguments);

            _tracer.TraceInformation($"Getting recommendation for {usageItems.Count} input items");
            lock (engine)
            {
                return(engine.Predict(usageItems, false)
                       .OrderByDescending(x => x.Score)
                       .Take(scoringArguments.RecommendationCount)
                       .ToArray());
            }
        }