public static void Main(string[] args) { Assembly assembly = Assembly.GetExecutingAssembly(); Assembly.LoadFile(Path.GetDirectoryName(assembly.Location) + Path.DirectorySeparatorChar + "MyMediaLiteExperimental.dll"); AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyMediaLite.Util.Handlers.UnhandledExceptionHandler); Console.CancelKeyPress += new ConsoleCancelEventHandler(AbortHandler); // recommender arguments string method = "MostPopular"; string recommender_options = string.Empty; // help/version bool show_help = false; bool show_version = false; // variables for iteration search int find_iter = 0; int max_iter = 500; double auc_cutoff = 0; double prec5_cutoff = 0; compute_fit = false; // other parameters string save_model_file = string.Empty; string load_model_file = string.Empty; int random_seed = -1; string prediction_file = string.Empty; test_ratio = 0; var p = new OptionSet() { // string-valued options { "training-file=", v => training_file = v }, { "test-file=", v => test_file = v }, { "recommender=", v => method = v }, { "recommender-options=", v => recommender_options += " " + v }, { "data-dir=", v => data_dir = v }, { "user-attributes=", v => user_attributes_file = v }, { "item-attributes=", v => item_attributes_file = v }, { "user-relations=", v => user_relations_file = v }, { "item-relations=", v => item_relations_file = v }, { "save-model=", v => save_model_file = v }, { "load-model=", v => load_model_file = v }, { "prediction-file=", v => prediction_file = v }, { "relevant-users=", v => relevant_users_file = v }, { "relevant-items=", v => relevant_items_file = v }, // integer-valued options { "find-iter=", (int v) => find_iter = v }, { "max-iter=", (int v) => max_iter = v }, { "random-seed=", (int v) => random_seed = v }, { "predict-items-number=", (int v) => predict_items_number = v }, // double-valued options // { "epsilon=", (double v) => epsilon = v }, { "auc-cutoff=", (double v) => auc_cutoff = v }, { "prec5-cutoff=", (double v) => prec5_cutoff = v }, { "test-ratio=", (double v) => test_ratio = v }, // enum options // * currently none * // boolean options { "compute-fit", v => compute_fit = v != null }, { "online-evaluation", v => online_eval = v != null }, { "filtered-evaluation", v => filtered_eval = v != null }, { "help", v => show_help = v != null }, { "version", v => show_version = v != null }, }; IList <string> extra_args = p.Parse(args); if (show_version) { ShowVersion(); } if (show_help) { Usage(0); } bool no_eval = test_file == null; if (training_file == null) { Usage("Parameter --training-file=FILE is missing."); } if (extra_args.Count > 0) { Usage("Did not understand " + extra_args[0]); } if (online_eval && filtered_eval) { Usage("Combination of --online-eval and --filtered-eval is not (yet) supported."); } if (random_seed != -1) { MyMediaLite.Util.Random.InitInstance(random_seed); } recommender = Recommender.CreateItemRecommender(method); if (recommender == null) { Usage(string.Format("Unknown method: '{0}'", method)); } Recommender.Configure(recommender, recommender_options, Usage); // load all the data LoadData(); Utils.DisplayDataStats(training_data, test_data, recommender); TimeSpan time_span; if (find_iter != 0) { var iterative_recommender = (IIterativeModel)recommender; Console.WriteLine(recommender.ToString() + " "); if (load_model_file == string.Empty) { iterative_recommender.Train(); } else { Recommender.LoadModel(iterative_recommender, load_model_file); } if (compute_fit) { Console.Write(string.Format(CultureInfo.InvariantCulture, "fit {0,0:0.#####} ", iterative_recommender.ComputeFit())); } var result = Evaluate(); Items.DisplayResults(result); Console.WriteLine(" iteration " + iterative_recommender.NumIter); for (int i = (int)iterative_recommender.NumIter + 1; i <= max_iter; i++) { TimeSpan t = Utils.MeasureTime(delegate() { iterative_recommender.Iterate(); }); training_time_stats.Add(t.TotalSeconds); if (i % find_iter == 0) { if (compute_fit) { double fit = 0; t = Utils.MeasureTime(delegate() { fit = iterative_recommender.ComputeFit(); }); fit_time_stats.Add(t.TotalSeconds); Console.Write(string.Format(CultureInfo.InvariantCulture, "fit {0,0:0.#####} ", fit)); } t = Utils.MeasureTime(delegate() { result = Evaluate(); }); eval_time_stats.Add(t.TotalSeconds); Items.DisplayResults(result); Console.WriteLine(" iteration " + i); Recommender.SaveModel(recommender, save_model_file, i); Predict(prediction_file, relevant_users_file, i); if (result["AUC"] < auc_cutoff || result["prec@5"] < prec5_cutoff) { Console.Error.WriteLine("Reached cutoff after {0} iterations.", i); Console.Error.WriteLine("DONE"); break; } } } // for DisplayStats(); } else { if (load_model_file == string.Empty) { Console.Write(recommender.ToString() + " "); time_span = Utils.MeasureTime(delegate() { recommender.Train(); }); Console.Write("training_time " + time_span + " "); } else { Recommender.LoadModel(recommender, load_model_file); Console.Write(recommender.ToString() + " "); // TODO is this the right time to load the model? } if (prediction_file != string.Empty) { Predict(prediction_file, relevant_users_file); } else if (!no_eval) { if (online_eval) { time_span = Utils.MeasureTime(delegate() { var result = Items.EvaluateOnline(recommender, test_data, training_data, relevant_users, relevant_items); // TODO support also for prediction outputs (to allow external evaluation) Items.DisplayResults(result); }); } else { time_span = Utils.MeasureTime(delegate() { var result = Evaluate(); Items.DisplayResults(result); }); } Console.Write(" testing_time " + time_span); } Console.WriteLine(); } Recommender.SaveModel(recommender, save_model_file); }
static void Main(string[] args) { Assembly assembly = Assembly.GetExecutingAssembly(); Assembly.LoadFile(Path.GetDirectoryName(assembly.Location) + Path.DirectorySeparatorChar + "MyMediaLiteExperimental.dll"); AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(Handlers.UnhandledExceptionHandler); Console.CancelKeyPress += new ConsoleCancelEventHandler(AbortHandler); // check number of command line parameters if (args.Length < 1) { Usage("Not enough arguments."); } // read command line parameters string method = args[0]; RecommenderParameters parameters = null; try { parameters = new RecommenderParameters(args, 1); } catch (ArgumentException e) { Usage(e.Message); } // arguments for iteration search find_iter = parameters.GetRemoveInt32("find_iter", 0); max_iter = parameters.GetRemoveInt32("max_iter", 500); epsilon = parameters.GetRemoveDouble("epsilon", 1); err_cutoff = parameters.GetRemoveDouble("err_cutoff", 2); // data arguments string data_dir = parameters.GetRemoveString("data_dir"); if (data_dir != string.Empty) { data_dir = data_dir + "/mml-track2"; } else { data_dir = "mml-track2"; } sample_data = parameters.GetRemoveBool("sample_data", false); predict_rated = parameters.GetRemoveBool("predict_rated", false); predict_score = parameters.GetRemoveBool("predict_score", false); // other arguments save_model_file = parameters.GetRemoveString("save_model"); load_model_file = parameters.GetRemoveString("load_model"); int random_seed = parameters.GetRemoveInt32("random_seed", -1); prediction_file = parameters.GetRemoveString("prediction_file"); if (predict_rated) { predict_score = true; } Console.Error.WriteLine("predict_score={0}", predict_score); if (random_seed != -1) { MyMediaLite.Util.Random.InitInstance(random_seed); } recommender_validate = Recommender.CreateItemRecommender(method); if (recommender_validate == null) { Usage(string.Format("Unknown method: '{0}'", method)); } Recommender.Configure(recommender_validate, parameters, Usage); recommender_final = recommender_validate.Clone() as ItemRecommender; if (parameters.CheckForLeftovers()) { Usage(-1); } // load all the data LoadData(data_dir); if (load_model_file != string.Empty) { Recommender.LoadModel(recommender_validate, load_model_file + "-validate"); Recommender.LoadModel(recommender_final, load_model_file + "-final"); } Console.Write(recommender_validate.ToString()); DoTrack2(); }
static void Main(string[] args) { Assembly assembly = Assembly.GetExecutingAssembly(); Assembly.LoadFile(Path.GetDirectoryName(assembly.Location) + Path.DirectorySeparatorChar + "MyMediaLiteExperimental.dll"); AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(Handlers.UnhandledExceptionHandler); Console.CancelKeyPress += new ConsoleCancelEventHandler(AbortHandler); // recommender arguments string method = "BiasedMatrixFactorization"; string recommender_options = string.Empty; // help/version bool show_help = false; bool show_version = false; // arguments for iteration search int find_iter = 0; int max_iter = 500; double epsilon = 0; double rmse_cutoff = double.MaxValue; double mae_cutoff = double.MaxValue; // data arguments string data_dir = string.Empty; string user_attributes_file = string.Empty; string item_attributes_file = string.Empty; string user_relations_file = string.Empty; string item_relations_file = string.Empty; // other arguments bool online_eval = false; bool search_hp = false; string save_model_file = string.Empty; string load_model_file = string.Empty; int random_seed = -1; string prediction_file = string.Empty; string prediction_line = "{0}\t{1}\t{2}"; int cross_validation = 0; double split_ratio = 0; var p = new OptionSet() { // string-valued options { "training-file=", v => training_file = v }, { "test-file=", v => test_file = v }, { "recommender=", v => method = v }, { "recommender-options=", v => recommender_options += " " + v }, { "data-dir=", v => data_dir = v }, { "user-attributes=", v => user_attributes_file = v }, { "item-attributes=", v => item_attributes_file = v }, { "user-relations=", v => user_relations_file = v }, { "item-relations=", v => item_relations_file = v }, { "save-model=", v => save_model_file = v }, { "load-model=", v => load_model_file = v }, { "prediction-file=", v => prediction_file = v }, { "prediction-line=", v => prediction_line = v }, // integer-valued options { "find-iter=", (int v) => find_iter = v }, { "max-iter=", (int v) => max_iter = v }, { "random-seed=", (int v) => random_seed = v }, { "cross-validation=", (int v) => cross_validation = v }, // double-valued options { "epsilon=", (double v) => epsilon = v }, { "rmse-cutoff=", (double v) => rmse_cutoff = v }, { "mae-cutoff=", (double v) => mae_cutoff = v }, { "split-ratio=", (double v) => split_ratio = v }, // enum options { "rating-type=", (RatingType v) => rating_type = v }, { "file-format=", (RatingFileFormat v) => file_format = v }, // boolean options { "compute-fit", v => compute_fit = v != null }, { "online-evaluation", v => online_eval = v != null }, { "search-hp", v => search_hp = v != null }, { "help", v => show_help = v != null }, { "version", v => show_version = v != null }, }; IList <string> extra_args = p.Parse(args); // TODO make sure interaction of --find-iter and --cross-validation works properly bool no_eval = test_file == null; if (show_version) { ShowVersion(); } if (show_help) { Usage(0); } if (extra_args.Count > 0) { Usage("Did not understand " + extra_args[0]); } if (training_file == null) { Usage("Parameter --training-file=FILE is missing."); } if (cross_validation != 0 && split_ratio != 0) { Usage("--cross-validation=K and --split-ratio=NUM are mutually exclusive."); } if (random_seed != -1) { MyMediaLite.Util.Random.InitInstance(random_seed); } recommender = Recommender.CreateRatingPredictor(method); if (recommender == null) { Usage(string.Format("Unknown method: '{0}'", method)); } Recommender.Configure(recommender, recommender_options, Usage); // ID mapping objects if (file_format == RatingFileFormat.KDDCUP_2011) { user_mapping = new IdentityMapping(); item_mapping = new IdentityMapping(); } // load all the data LoadData(data_dir, user_attributes_file, item_attributes_file, user_relations_file, item_relations_file, !online_eval); Console.Error.WriteLine(string.Format(CultureInfo.InvariantCulture, "ratings range: [{0}, {1}]", recommender.MinRating, recommender.MaxRating)); if (split_ratio > 0) { var split = new RatingsSimpleSplit(training_data, split_ratio); recommender.Ratings = split.Train[0]; training_data = split.Train[0]; test_data = split.Test[0]; } Utils.DisplayDataStats(training_data, test_data, recommender); if (find_iter != 0) { if (!(recommender is IIterativeModel)) { Usage("Only iterative recommenders support find_iter."); } var iterative_recommender = (IIterativeModel)recommender; Console.WriteLine(recommender.ToString() + " "); if (load_model_file == string.Empty) { recommender.Train(); } else { Recommender.LoadModel(iterative_recommender, load_model_file); } if (compute_fit) { Console.Write(string.Format(CultureInfo.InvariantCulture, "fit {0,0:0.#####} ", iterative_recommender.ComputeFit())); } MyMediaLite.Eval.Ratings.DisplayResults(MyMediaLite.Eval.Ratings.Evaluate(recommender, test_data)); Console.WriteLine(" iteration " + iterative_recommender.NumIter); for (int i = (int)iterative_recommender.NumIter + 1; i <= max_iter; i++) { TimeSpan time = Utils.MeasureTime(delegate() { iterative_recommender.Iterate(); }); training_time_stats.Add(time.TotalSeconds); if (i % find_iter == 0) { if (compute_fit) { double fit = 0; time = Utils.MeasureTime(delegate() { fit = iterative_recommender.ComputeFit(); }); fit_time_stats.Add(time.TotalSeconds); Console.Write(string.Format(CultureInfo.InvariantCulture, "fit {0,0:0.#####} ", fit)); } Dictionary <string, double> results = null; time = Utils.MeasureTime(delegate() { results = MyMediaLite.Eval.Ratings.Evaluate(recommender, test_data); }); eval_time_stats.Add(time.TotalSeconds); MyMediaLite.Eval.Ratings.DisplayResults(results); rmse_eval_stats.Add(results["RMSE"]); Console.WriteLine(" iteration " + i); Recommender.SaveModel(recommender, save_model_file, i); if (prediction_file != string.Empty) { Prediction.WritePredictions(recommender, test_data, user_mapping, item_mapping, prediction_line, prediction_file + "-it-" + i); } if (epsilon > 0.0 && results["RMSE"] - rmse_eval_stats.Min() > epsilon) { Console.Error.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0} >> {1}", results["RMSE"], rmse_eval_stats.Min())); Console.Error.WriteLine("Reached convergence on training/validation data after {0} iterations.", i); break; } if (results["RMSE"] > rmse_cutoff || results["MAE"] > mae_cutoff) { Console.Error.WriteLine("Reached cutoff after {0} iterations.", i); break; } } } // for DisplayStats(); } else { TimeSpan seconds; if (load_model_file == string.Empty) { if (cross_validation > 0) { Console.Write(recommender.ToString()); Console.WriteLine(); var split = new RatingCrossValidationSplit(training_data, cross_validation); var results = MyMediaLite.Eval.Ratings.EvaluateOnSplit(recommender, split); // TODO if (search_hp) MyMediaLite.Eval.Ratings.DisplayResults(results); no_eval = true; recommender.Ratings = training_data; } else { if (search_hp) { // TODO --search-hp-criterion=RMSE double result = NelderMead.FindMinimum("RMSE", recommender); Console.Error.WriteLine("estimated quality (on split) {0}", result.ToString(CultureInfo.InvariantCulture)); // TODO give out hp search time } Console.Write(recommender.ToString()); seconds = Utils.MeasureTime(delegate() { recommender.Train(); }); Console.Write(" training_time " + seconds + " "); } } else { Recommender.LoadModel(recommender, load_model_file); Console.Write(recommender.ToString() + " "); } if (!no_eval) { if (online_eval) // TODO support also for prediction outputs (to allow external evaluation) { seconds = Utils.MeasureTime(delegate() { MyMediaLite.Eval.Ratings.DisplayResults(MyMediaLite.Eval.Ratings.EvaluateOnline(recommender, test_data)); }); } else { seconds = Utils.MeasureTime(delegate() { MyMediaLite.Eval.Ratings.DisplayResults(MyMediaLite.Eval.Ratings.Evaluate(recommender, test_data)); }); } Console.Write(" testing_time " + seconds); } if (compute_fit) { Console.Write("fit "); seconds = Utils.MeasureTime(delegate() { MyMediaLite.Eval.Ratings.DisplayResults(MyMediaLite.Eval.Ratings.Evaluate(recommender, training_data)); }); Console.Write(string.Format(CultureInfo.InvariantCulture, " fit_time {0,0:0.#####} ", seconds)); } if (prediction_file != string.Empty) { seconds = Utils.MeasureTime(delegate() { Console.WriteLine(); Prediction.WritePredictions(recommender, test_data, user_mapping, item_mapping, prediction_line, prediction_file); }); Console.Error.Write("predicting_time " + seconds); } Console.WriteLine(); Console.Error.WriteLine("memory {0}", Memory.Usage); } Recommender.SaveModel(recommender, save_model_file); }
public static void Main(string[] args) { AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(Handlers.UnhandledExceptionHandler); // check number of command line parameters if (args.Length < 4) { Usage("Not enough arguments."); } // read command line parameters RecommenderParameters parameters = null; try { parameters = new RecommenderParameters(args, 4); } catch (ArgumentException e) { Usage(e.Message); } // other parameters string data_dir = parameters.GetRemoveString("data_dir"); //Console.Error.WriteLine("data_dir " + data_dir); string item_attributes_file = parameters.GetRemoveString("item_attributes"); string user_attributes_file = parameters.GetRemoveString("user_attributes"); //string save_mapping_file = parameters.GetRemoveString( "save_model"); int random_seed = parameters.GetRemoveInt32("random_seed", -1); bool no_eval = parameters.GetRemoveBool("no_eval", false); bool compute_fit = parameters.GetRemoveBool("compute_fit", false); string prediction_file = parameters.GetRemoveString("prediction_file"); if (random_seed != -1) { MyMediaLite.Util.Random.InitInstance(random_seed); } // main data files and method string trainfile = args[0].Equals("-") ? "-" : Path.Combine(data_dir, args[0]); string testfile = args[1].Equals("-") ? "-" : Path.Combine(data_dir, args[1]); string load_model_file = args[2]; string method = args[3]; // set correct recommender switch (method) { case "MF-ItemMapping": recommender = Recommender.Configure(mf_map, parameters, Usage); break; // case "MF-ItemMapping-Optimal": // recommender = Recommender.Configure(mf_map_opt, parameters, Usage); // break; // case "BPR-MF-ItemMapping-kNN": // recommender = Recommender.Configure(mf_map_knn, parameters, Usage); // break; // case "BPR-MF-ItemMapping-SVR": // recommender = Recommender.Configure(mf_map_svr, parameters, Usage); // break; default: Usage(string.Format("Unknown method: '{0}'", method)); break; } if (parameters.CheckForLeftovers()) { Usage(-1); } // TODO move loading into its own method // ID mapping objects EntityMapping user_mapping = new EntityMapping(); EntityMapping item_mapping = new EntityMapping(); // training data training_data = MyMediaLite.IO.RatingPrediction.Read(Path.Combine(data_dir, trainfile), user_mapping, item_mapping); recommender.Ratings = training_data; // user attributes if (recommender is IUserAttributeAwareRecommender) { if (user_attributes_file.Equals(string.Empty)) { Usage("Recommender expects user_attributes=FILE."); } else { ((IUserAttributeAwareRecommender)recommender).UserAttributes = AttributeData.Read(Path.Combine(data_dir, user_attributes_file), user_mapping); } } // item attributes if (recommender is IItemAttributeAwareRecommender) { if (item_attributes_file.Equals(string.Empty)) { Usage("Recommender expects item_attributes=FILE."); } else { ((IItemAttributeAwareRecommender)recommender).ItemAttributes = AttributeData.Read(Path.Combine(data_dir, item_attributes_file), item_mapping); } } // test data test_data = MyMediaLite.IO.RatingPrediction.Read(Path.Combine(data_dir, testfile), user_mapping, item_mapping); TimeSpan seconds; Recommender.LoadModel(recommender, load_model_file); // set the maximum user and item IDs in the recommender - this is important for the cold start use case recommender.MaxUserID = user_mapping.InternalIDs.Max(); recommender.MaxItemID = item_mapping.InternalIDs.Max(); Console.Error.WriteLine(string.Format(CultureInfo.InvariantCulture, "ratings range: [{0}, {1}]", recommender.MinRating, recommender.MaxRating)); DisplayDataStats(); Console.Write(recommender.ToString() + " "); if (compute_fit) { seconds = Utils.MeasureTime(delegate() { int num_iter = recommender.NumIterMapping; recommender.NumIterMapping = 0; recommender.LearnAttributeToFactorMapping(); Console.Error.WriteLine(); Console.Error.WriteLine(string.Format(CultureInfo.InvariantCulture, "iteration {0} fit {1}", -1, recommender.ComputeFit())); recommender.NumIterMapping = 1; for (int i = 0; i < num_iter; i++, i++) { recommender.IterateMapping(); Console.Error.WriteLine(string.Format(CultureInfo.InvariantCulture, "iteration {0} fit {1}", i, recommender.ComputeFit())); } recommender.NumIterMapping = num_iter; // restore }); } else { seconds = Utils.MeasureTime(delegate() { recommender.LearnAttributeToFactorMapping(); }); } Console.Write("mapping_time " + seconds + " "); if (!no_eval) { seconds = EvaluateRecommender(recommender); } Console.WriteLine(); if (prediction_file != string.Empty) { Console.WriteLine(); seconds = Utils.MeasureTime( delegate() { Prediction.WritePredictions(recommender, test_data, user_mapping, item_mapping, prediction_file); } ); Console.Error.WriteLine("predicting_time " + seconds); } }
static void Main(string[] args) { Assembly assembly = Assembly.GetExecutingAssembly(); Assembly.LoadFile(Path.GetDirectoryName(assembly.Location) + Path.DirectorySeparatorChar + "MyMediaLiteExperimental.dll"); double min_rating = 0; double max_rating = 100; AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(Handlers.UnhandledExceptionHandler); Console.CancelKeyPress += new ConsoleCancelEventHandler(AbortHandler); // check number of command line parameters if (args.Length < 1) { Usage("Not enough arguments."); } // read command line parameters string method = args[0]; RecommenderParameters parameters = null; try { parameters = new RecommenderParameters(args, 1); } catch (ArgumentException e) { Usage(e.Message); } // arguments for iteration search find_iter = parameters.GetRemoveInt32("find_iter", 0); max_iter = parameters.GetRemoveInt32("max_iter", 500); compute_fit = parameters.GetRemoveBool("compute_fit", false); epsilon = parameters.GetRemoveDouble("epsilon", 0); rmse_cutoff = parameters.GetRemoveDouble("rmse_cutoff", double.MaxValue); mae_cutoff = parameters.GetRemoveDouble("mae_cutoff", double.MaxValue); // data arguments string data_dir = parameters.GetRemoveString("data_dir"); track2 = parameters.GetRemoveBool("track2", false); if (data_dir != string.Empty) { data_dir = data_dir + (track2 ? "/mml-track2" : "/track1"); } else { data_dir = track2 ? "/mml-track2" : "track1"; } sample_data = parameters.GetRemoveBool("sample_data", false); // other arguments save_model_file = parameters.GetRemoveString("save_model"); load_model_file = parameters.GetRemoveString("load_model"); int random_seed = parameters.GetRemoveInt32("random_seed", -1); no_eval = parameters.GetRemoveBool("no_eval", false); prediction_file = parameters.GetRemoveString("prediction_file"); cross_validation = parameters.GetRemoveInt32("cross_validation", 0); good_rating_prob = parameters.GetRemoveBool("good_rating_prob", false); if (good_rating_prob) { max_rating = 1; } if (random_seed != -1) { MyMediaLite.Util.Random.InitInstance(random_seed); } recommender = Recommender.CreateRatingPredictor(method); if (recommender == null) { Usage(string.Format("Unknown method: '{0}'", method)); } Recommender.Configure(recommender, parameters, Usage); if (parameters.CheckForLeftovers()) { Usage(-1); } // load all the data TimeSpan loading_time = Utils.MeasureTime(delegate() { LoadData(data_dir); }); Console.Error.WriteLine(string.Format(CultureInfo.InvariantCulture, "loading_time {0,0:0.##}", loading_time.TotalSeconds)); recommender.Ratings = training_ratings; recommender.MinRating = min_rating; recommender.MaxRating = max_rating; Console.Error.WriteLine(string.Format(CultureInfo.InvariantCulture, "ratings range: [{0}, {1}]", recommender.MinRating, recommender.MaxRating)); if (load_model_file != string.Empty) { Recommender.LoadModel(recommender, load_model_file); } DoTrack1(); Console.Error.WriteLine("memory {0}", Memory.Usage); }