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}'"); } }
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'"); }