public void MAETest() { var actual = new Matrix(4, 1); var expected = new Matrix(4, 1); actual.InRandomize(); expected.InRandomize(); var autoErr = new MAE().Evaluate(actual, expected); var error = 0.0; for (var i = 0; i < actual.Rows; i++) { for (var j = 0; j < actual.Columns; j++) { error += Math.Abs(expected[i, j] - actual[i, j]); } } error /= actual.Rows * actual.Columns; Assert.IsTrue(Math.Abs(error - autoErr) < 0.01, new MAE().Type().ToString() + " Forward!"); var autoDErr = new MAE().Backward(actual, expected); var dErr = new Matrix(actual.Rows, actual.Columns); for (var i = 0; i < actual.Rows; i++) { for (var j = 0; j < actual.Columns; j++) { dErr[i, j] = Math.Sign(actual[i, j] - expected[i, j]); } } Assert.IsTrue(Math.Abs(dErr.FrobeniusNorm() - autoDErr.FrobeniusNorm()) < 0.01, new MAE().Type().ToString() + " Backward!"); }
public string RunNMFbasedOMF(int maxEpoch, double learnRate, double regularization, int factorCount, List <double> quantizer, int topN = 0) { if (!ReadyForNumerical) { GetReadyForNumerical(); } StringBuilder log = new StringBuilder(); log.AppendLine(Utils.PrintHeading("NMF based OMF")); // NMF Prediction // Get ratings from scorer, for both train and test // R_all contains indexes of all ratings both train and test DataMatrix R_all = new DataMatrix(R_unknown.UserCount, R_unknown.ItemCount); R_all.MergeNonOverlap(R_unknown); R_all.MergeNonOverlap(R_train.IndexesOfNonZeroElements()); Utils.StartTimer(); DataMatrix R_predictedByNMF = NMF.PredictRatings(R_train, R_all, maxEpoch, learnRate, regularization, factorCount); log.AppendLine(Utils.StopTimer()); // OMF Prediction log.AppendLine(Utils.PrintHeading("Ordinal Matrix Factorization with NMF as scorer")); Utils.StartTimer(); Dictionary <Tuple <int, int>, List <double> > OMFDistributionByUserItem; DataMatrix R_predicted; log.AppendLine(OMF.PredictRatings(R_train.Matrix, R_unknown.Matrix, R_predictedByNMF.Matrix, quantizer, out R_predicted, out OMFDistributionByUserItem)); log.AppendLine(Utils.StopTimer()); // Numerical Evaluation log.AppendLine(Utils.PrintValue("RMSE", RMSE.Evaluate(R_test, R_predicted).ToString("0.0000"))); log.AppendLine(Utils.PrintValue("MAE", MAE.Evaluate(R_test, R_predicted).ToString("0.0000"))); // TopN Evaluation if (topN != 0) { var topNItemsByUser = ItemRecommendationCore.GetTopNItemsByUser(R_predicted, topN); for (int n = 1; n <= topN; n++) { log.AppendLine(Utils.PrintValue("NCDG@" + n, NCDG.Evaluate(RelevantItemsByUser, topNItemsByUser, n).ToString("0.0000"))); } for (int n = 1; n <= topN; n++) { log.AppendLine(Utils.PrintValue("MAP@" + n, MAP.Evaluate(RelevantItemsByUser, topNItemsByUser, n).ToString("0.0000"))); } } // Save OMFDistribution to file if (!File.Exists(GetDataFileName("RatingOMF_"))) { Utils.IO <Dictionary <Tuple <int, int>, List <double> > > .SaveObject(OMFDistributionByUserItem, GetDataFileName("RatingOMF_")); } return(log.ToString()); }
/// <summary> /// Rating based Non-negative Matrix Factorization /// </summary> public string RunNMF(int maxEpoch, double learnRate, double regularization, int factorCount, int topN = 0) { if (!ReadyForNumerical) { GetReadyForNumerical(); } StringBuilder log = new StringBuilder(); log.AppendLine(Utils.PrintHeading("NMF")); // Prediction Utils.StartTimer(); DataMatrix R_predicted = NMF.PredictRatings(R_train, R_unknown, maxEpoch, learnRate, regularization, factorCount); log.AppendLine(Utils.StopTimer()); // Numerical Evaluation log.AppendLine(Utils.PrintValue("RMSE", RMSE.Evaluate(R_test, R_predicted).ToString("0.0000"))); log.AppendLine(Utils.PrintValue("MAE", MAE.Evaluate(R_test, R_predicted).ToString("0.0000"))); // TopN Evaluation if (topN != 0) { var topNItemsByUser = ItemRecommendationCore.GetTopNItemsByUser(R_predicted, topN); for (int n = 1; n <= topN; n++) { log.AppendLine(Utils.PrintValue("NCDG@" + n, NCDG.Evaluate(RelevantItemsByUser, topNItemsByUser, n).ToString("0.0000"))); } for (int n = 1; n <= topN; n++) { log.AppendLine(Utils.PrintValue("MAP@" + n, MAP.Evaluate(RelevantItemsByUser, topNItemsByUser, n).ToString("0.0000"))); } } return(log.ToString()); }
/// <summary> /// Predict all unknown values as global mean rating. /// </summary> public string RunGlobalMean() { if (!ReadyForNumerical) { GetReadyForNumerical(); } StringBuilder log = new StringBuilder(); log.AppendLine(Utils.PrintHeading("Global Mean")); // Prediction Utils.StartTimer(); double globalMean = R_train.GetGlobalMean(); DataMatrix R_predicted = R_unknown.Multiply(globalMean); log.AppendLine(Utils.StopTimer()); // Numerical Evaluation log.AppendLine(Utils.PrintValue("RMSE", RMSE.Evaluate(R_test, R_predicted).ToString("0.0000"))); log.AppendLine(Utils.PrintValue("MAE", MAE.Evaluate(R_test, R_predicted).ToString("0.0000"))); return(log.ToString()); }
public string RunUserKNN(int topN = 0) { if (!ReadyForNumerical) { GetReadyForNumerical(); } StringBuilder log = new StringBuilder(); log.AppendLine(Utils.PrintHeading("UserKNN")); // Prediction Utils.StartTimer(); DataMatrix R_predicted = Numerical.UserKNN.PredictRatings(R_train, R_unknown, UserSimilaritiesOfRating, MaxCountOfNeighbors); log.AppendLine(Utils.StopTimer()); // Numerical Evaluation log.AppendLine(Utils.PrintValue("RMSE", RMSE.Evaluate(R_test, R_predicted).ToString("0.0000"))); log.AppendLine(Utils.PrintValue("MAE", MAE.Evaluate(R_test, R_predicted).ToString("0.0000"))); // TopN Evaluation if (topN != 0) { var topNItemsByUser = ItemRecommendationCore.GetTopNItemsByUser(R_predicted, topN); for (int n = 1; n <= topN; n++) { Utils.PrintValue("NCDG@" + n, NCDG.Evaluate(RelevantItemsByUser, topNItemsByUser, n).ToString("0.0000")); } for (int n = 1; n <= topN; n++) { log.AppendLine(Utils.PrintValue("MAP@" + n, MAP.Evaluate(RelevantItemsByUser, topNItemsByUser, n).ToString("0.0000"))); } } return(log.ToString()); }
// 运行一次算法 private void button1_Click(object sender, EventArgs e) { // 记录当前时间 DateTime dt_1 = DateTime.Now; this.Rec_Items_num = int.Parse(this.textBox13.Text); // Top-N推荐个数 this.progressBar1.Maximum = this.comboBox2.SelectedIndex + 15 + 22; this.progressBar1.Value = 0; // 读入数据,生成UI矩阵 this.textBox3.Text = "开始读入数据"; this.progressBar1.Value++; Application.DoEvents(); cReadinData obj_ReadData = new cReadinData(comboBox1.SelectedIndex); this.textBox3.Text = "读入数据完成 训练数据:" + obj_ReadData.sTrainFileName[comboBox1.SelectedIndex] + " 测试数据:" + obj_ReadData.testfileName[comboBox1.SelectedIndex]; this.progressBar1.Value++; Application.DoEvents(); int number = int.Parse(textBox2.Text); this.neigh_num = number; // 相似度算法的选择 if (this.radioButton1.Checked) { sim_alg = 1; } else if (this.radioButton2.Checked) { sim_alg = 2; } else if (this.radioButton3.Checked) { sim_alg = 3; } // 测试用户数目,最少为15 testUserNum = this.comboBox2.SelectedIndex + 15; this.textBox3.Text = "初始化最大邻居个数"; // 初始化,最近邻居数量最大为200 obj_ItemBased_CF = new cItemBased_CF(200); this.progressBar1.Value++; Application.DoEvents(); // 初始化相关数据 for (int i = 1; i <= 1682; i++) { this.textBox3.Text = "初始 " + i + " 个项目数据"; if ((i % 100) == 0) { this.progressBar1.Value++; Application.DoEvents(); } Application.DoEvents(); obj_ItemBased_CF.generateItemNN(i); } this.progressBar1.Value++; Application.DoEvents(); this.textBox3.Text = "读取最近邻居及其相似值文件"; obj_ItemBased_CF.readFile(); this.progressBar1.Value++; Application.DoEvents(); // 得到测试用户集合 cUser[] testUsers = cReadinData.getTestUser(); this.textBox3.Text = "读取测试用户集合"; this.progressBar1.Value++; Application.DoEvents(); double MAE, Precison, Recall, F_Measure; double total_MAE = 0, total_Precison = 0, total_Recall = 0, total_F_Measure = 0; double average_MAE, average_Precison, average_Recall, average_F_Measure; // for循环为每个测试用户产生预测评分以及Top-N推荐,并取得算法评价指标 for (int i = 1; i <= testUserNum; i++) { obj_AssStrategy = obj_ItemBased_CF.getPredictRating(testUsers[i], this.sim_alg, neigh_num, Rec_Items_num); MAE = obj_AssStrategy.MAE; Precison = obj_AssStrategy.Precison; Recall = obj_AssStrategy.Recall; F_Measure = obj_AssStrategy.calculateF_Measure(); // 累计各项指标的和 total_MAE += MAE; total_Precison += Precison; total_Recall += Recall; total_F_Measure += F_Measure; this.textBox3.Text = "第" + i.ToString() + "个用户 MAE:" + MAE.ToString() + " 查准率:" + Precison + " 查全率:" + Recall + " F值:" + F_Measure; this.progressBar1.Value++; Application.DoEvents(); } // 计算各项指标的平均值 average_MAE = total_MAE / this.testUserNum; average_Precison = total_Precison / this.testUserNum; average_Recall = total_Recall / this.testUserNum; average_F_Measure = total_F_Measure / this.testUserNum; DateTime dt_2 = DateTime.Now; TimeSpan ts = dt_2.Subtract(dt_1); this.textBox3.Text = "完成 平均MAE:" + average_MAE.ToString() + " 平均查准率:" + average_Precison + " 平均查全率:" + average_Recall + " 平均F值:" + average_F_Measure + " 总耗时:" + ts.TotalMilliseconds + "ms"; Application.DoEvents(); this.textBox4.Text = average_MAE.ToString(); this.textBox5.Text = ts.TotalMilliseconds + "ms"; this.textBox6.Text = this.sSimAlg[this.sim_alg - 1]; this.textBox7.Text = this.neigh_num.ToString(); this.textBox9.Text = average_Precison.ToString(); this.textBox10.Text = average_Recall.ToString(); this.textBox11.Text = average_F_Measure.ToString(); this.textBox12.Text = Rec_Items_num.ToString(); string log = this.sSimAlg[this.sim_alg - 1] + " 邻居数:" + this.neigh_num.ToString() + " 平均MAE:" + average_MAE.ToString() + " 平均查准率:" + average_Precison + " 平均查全率:" + average_Recall + " 平均F值:" + average_F_Measure + " 总耗时:" + ts.TotalMilliseconds + "ms"; this.dataGridView1.Rows.Add(count_dgv++, sSimAlg[sim_alg - 1], this.neigh_num, this.Rec_Items_num, average_MAE, average_Precison, average_Recall, average_F_Measure, (ts.TotalMilliseconds / this.testUserNum) + " ms"); }