static void Main(string[] args)
        {
            Console.WriteLine("Restaurants recommender");

            MLContext mlContext = new MLContext(0);

            var trainingDataFile = "Data\\trainingData.tsv";

            DataPreparer.PreprocessData(trainingDataFile);

            IDataView trainingDataView = mlContext
                                         .Data
                                         .LoadFromTextFile <ModelInput>
                                             (trainingDataFile, hasHeader: true);

            var dataProcessingPipeline =
                mlContext
                .Transforms
                .Conversion
                .MapValueToKey(outputColumnName: "UserIdEncoded",
                               inputColumnName: nameof(ModelInput.UserId))
                .Append(mlContext
                        .Transforms
                        .Conversion
                        .MapValueToKey(outputColumnName: "RestaurantNameEncoded",
                                       inputColumnName: nameof(ModelInput.RestaurantName)));

            var finalOptions = new MatrixFactorizationTrainer.Options
            {
                MatrixColumnIndexColumnName = "UserIdEncoded",
                MatrixRowIndexColumnName    = "RestaurantNameEncoded",
                LabelColumnName             = "TotalRating",
                NumberOfIterations          = 10,
                ApproximationRank           = 200,
                Quiet = true
            };

            var trainer          = mlContext.Recommendation().Trainers.MatrixFactorization(finalOptions);
            var trainingPipeLine = dataProcessingPipeline.Append(trainer);

            Console.WriteLine("Training model");
            var model = trainingPipeLine.Fit(trainingDataView);

            // View results
            var testUserId = "U1134";

            var predictionEngine = mlContext
                                   .Model
                                   .CreatePredictionEngine <ModelInput, ModelOutput>(model);

            var alreadyRatedRestaurants =
                mlContext
                .Data
                .CreateEnumerable <ModelInput>(trainingDataView, false)
                .Where(i => i.UserId == testUserId)
                .Select(r => r.RestaurantName)
                .Distinct();

            var allRestaurantNames = trainingDataView
                                     .GetColumn <string>("RestaurantName")
                                     .Distinct()
                                     .Where(r => !alreadyRatedRestaurants.Contains(r));

            var scoredRestaurants =
                allRestaurantNames.Select(restName =>
            {
                var prediction = predictionEngine.Predict(
                    new ModelInput()
                {
                    RestaurantName = restName,
                    UserId         = testUserId
                });

                return(RestaurantName: restName, PredictedRating: prediction.Score);
            });

            var top10Restaurants = scoredRestaurants
                                   .OrderByDescending(s => s.PredictedRating)
                                   .Take(10);

            Console.WriteLine();
            Console.WriteLine($"Top 10 restaurants for {testUserId}");
            Console.WriteLine($"----------------------------");

            foreach (var input in top10Restaurants)
            {
                Console.WriteLine($"Predicted rating [{input.PredictedRating:#.0}] for restaurant: '{input.RestaurantName}'");
            }
        }
예제 #2
0
        static void Main(string[] args)
        {
            Console.WriteLine("Restaurants recommender");

            MLContext mlContext = new MLContext(0);

            var trainingDataFile = "Data\\trainingData.tsv";

            DataPreparer.PreprocessData(trainingDataFile);

            IDataView trainingDataView = mlContext
                                         .Data
                                         .LoadFromTextFile <ModelInput>
                                             (trainingDataFile, hasHeader: true);

            var dataProcessingPipeline =
                mlContext
                .Transforms
                .Conversion
                .MapValueToKey(outputColumnName: "UserIdEncoded",
                               inputColumnName: nameof(ModelInput.UserId))
                .Append(mlContext
                        .Transforms
                        .Conversion
                        .MapValueToKey(outputColumnName: "RestaurantNameEncoded",
                                       inputColumnName: nameof(ModelInput.RestaurantName)));

            var finalOptions = new MatrixFactorizationTrainer.Options
            {
                MatrixColumnIndexColumnName = "UserIdEncoded",
                MatrixRowIndexColumnName    = "RestaurantNameEncoded",
                LabelColumnName             = "TotalRating",
                NumberOfIterations          = 10,
                ApproximationRank           = 200,
                Quiet = true
            };

            var trainer          = mlContext.Recommendation().Trainers.MatrixFactorization(finalOptions);
            var trainingPipeLine = dataProcessingPipeline.Append(trainer);

            Console.WriteLine("Training model");
            var model = trainingPipeLine.Fit(trainingDataView);

            //// View results
            //var testUserId = "U1134";

            var predictionEngine = mlContext
                                   .Model
                                   .CreatePredictionEngine <ModelInput, ModelOutput>(model);

            //var alreadyRatedRestaurants =
            //    mlContext
            //        .Data
            //        .CreateEnumerable<ModelInput>(trainingDataView, false)
            //        .Where(i => i.UserId == testUserId)
            //        .Select(r => r.RestaurantName)
            //        .Distinct();

            //var allRestaurantNames = trainingDataView
            //   .GetColumn<string>("RestaurantName")
            //   .Distinct()
            //   .Where(r => !alreadyRatedRestaurants.Contains(r));

            //var scoredRestaurants =
            //        allRestaurantNames.Select(restName =>
            //        {
            //            var prediction = predictionEngine.Predict(
            //                                    new ModelInput()
            //                                    {
            //                                        RestaurantName = restName,
            //                                        UserId = testUserId
            //                                    });

            //            return (RestaurantName: restName, PredictedRating: prediction.Score);
            //        });

            //var top10Restaurants = scoredRestaurants
            //                        .OrderByDescending(s => s.PredictedRating)
            //                        .Take(10);

            //Console.WriteLine();
            //Console.WriteLine($"Top 10 restaurants for {testUserId}");
            //Console.WriteLine($"----------------------------");

            //foreach (var input in top10Restaurants)
            //{
            //    Console.WriteLine($"Predicted rating [{input.PredictedRating:#.0}] for restaurant: '{input.RestaurantName}'");
            //}

            var crossValMetrics = mlContext.Recommendation()
                                  .CrossValidate(data: trainingDataView,
                                                 estimator: trainingPipeLine,
                                                 labelColumnName: "TotalRating"
                                                 );

            var averageRMSE     = crossValMetrics.Average(m => m.Metrics.RootMeanSquaredError);
            var averageRSquared = crossValMetrics.Average(m => m.Metrics.RSquared);

            Console.WriteLine();
            Console.WriteLine($"--- Metrics before tuning hyper parameters ---");
            Console.WriteLine($"Cross validated root mean square error: {averageRMSE:#.000}");
            Console.WriteLine($"Cross validated RSquared: {averageRSquared:#.000}");
            Console.WriteLine();

            //HyperParameterExploration(mlContext, dataProcessingPipeline, trainingDataView);

            var prediction = predictionEngine.Predict(
                new ModelInput()
            {
                UserId         = "CLONED",
                RestaurantName = "Restaurant Wu Zhuo Yi"
            });

            Console.WriteLine($"Predicted: {prediction.Score:#.0} for 'Restaurant Wu Zhuo Yi'");
        }