public static double Calculate(cUser user1, cUser user2)
        {
            double numerator = 0;
            double denominator1 = 0, denominator2 = 0, denominator = 0;
            double average1, average2;
            double result;

            average1 = user1.getTotalRating() / user1.RatingNums;
            average2 = user2.getTotalRating() / user2.RatingNums;

            for (int i = 1; i < 1683; i++)
            {
                if (user1.Ratings[i] != 0 && user2.Ratings[i] != 0)
                {
                    numerator += (user1.Ratings[i] - average1) * (user2.Ratings[i] - average2);
                }
                if (user1.Ratings[i] != 0)
                {
                    denominator1 += Math.Pow(user1.Ratings[i] - average1, 2);
                }
                if (user2.Ratings[i] != 0)
                {
                    denominator2 += Math.Pow(user2.Ratings[i] - average2, 2);
                }
            }
            denominator = Math.Sqrt(denominator1) * Math.Sqrt(denominator2);
            if (denominator == 0)
            {
                return(0);
            }
            result = numerator / denominator;
            return(result);
        }
        public static double Calculate(cUser user1, cUser user2)
        {
            double numerator = 0;
            double denominator1 = 0, denominator2 = 0, denominator = 0;
            double average1, average2;
            double result;

            average1 = user1.getTotalRating() / user1.RatingNums;
            average2 = user2.getTotalRating() / user2.RatingNums;

            for (int i = 1; i < 1683; i++)
            {
                if (user1.Ratings[i] != 0 && user2.Ratings[i] != 0)
                {
                    numerator += (user1.Ratings[i] - average1) * (user2.Ratings[i] - average2);
                }
                if (user1.Ratings[i] != 0)
                {
                    denominator1 += Math.Pow(user1.Ratings[i] - average1, 2);
                }
                if (user2.Ratings[i] != 0)
                {
                    denominator2 += Math.Pow(user2.Ratings[i] - average2, 2);
                }
            }
            denominator = Math.Sqrt(denominator1) * Math.Sqrt(denominator2);
            if (denominator == 0)
                return 0;
            result = numerator / denominator;
            return result;
        }
        // 计算向量余弦值
        public static double Calculate(cUser objUser1, cUser objUser2)
        {
            double dotProduct = CalcDotProduct(objUser1, objUser2);
            double length1 = CalcLength(objUser1);
            double length2 = CalcLength(objUser2);
            double cosine = dotProduct / (length1 * length2);

            return cosine;
        }
        // 计算向量余弦值
        public static double Calculate(cUser objUser1, cUser objUser2)
        {
            double dotProduct = CalcDotProduct(objUser1, objUser2);
            double length1    = CalcLength(objUser1);
            double length2    = CalcLength(objUser2);
            double cosine     = dotProduct / (length1 * length2);

            return(cosine);
        }
        // 计算向量长度(vector length)
        private static double CalcLength(cUser objUser)
        {
            double length = 0;
            for (int i = 1; i < 1683; i++)
            {
                length += Math.Pow(objUser.Ratings[i], 2);
            }

            return Math.Sqrt(length);
        }
        /// <summary>
        /// 读入训练数据
        /// </summary>
        /// <param name="iTrainFileNumber">数据集的选择</param>
        private void readTrainData(int iTrainFileNumber)
        {
            string       sLine = "";
            StreamReader rs    = null;

            try
            {
                rs = new StreamReader(sTrainFileName[iTrainFileNumber], Encoding.Default);
            }
            catch (Exception e)
            {
                MessageBox.Show("未找到数据文件", "ERROR");
                return;
            }
            int user, item, rating;
            int countUser = 0, prev = 0, countRating = 0;

            while (sLine != null)
            {
                sLine = rs.ReadLine();

                if (sLine == null)
                {
                    objUser[countUser].RatingNums = countRating;
                    break;
                }

                string sUser = sLine.Substring(0, sLine.IndexOf('\t'));
                string temp  = sLine.Substring(sUser.Length + 1);
                string sItem = temp.Substring(0, temp.IndexOf('\t'));
                temp = sLine.Substring(sUser.Length + sItem.Length + 2, 1);

                user = int.Parse(sUser);

                // 新用户
                if (prev != user)
                {
                    prev = user;

                    if (countUser != 0)
                    {
                        objUser[countUser].RatingNums = countRating;
                    }
                    countRating          = 0;
                    objUser[++countUser] = new cUser(user);
                }

                item   = int.Parse(sItem);
                rating = int.Parse(temp);
                countRating++;

                objUser[countUser].Ratings[item] = rating;
            }
            //   Console.WriteLine("Total User num:{0}", this.objUser.Length);
        }
        // 计算向量长度(vector length)
        private static double CalcLength(cUser objUser)
        {
            double length = 0;

            for (int i = 1; i < 1683; i++)
            {
                length += Math.Pow(objUser.Ratings[i], 2);
            }

            return(Math.Sqrt(length));
        }
        // 计算向量点积(dot product)/内积(inner product)
        private static double CalcDotProduct(cUser objUser1, cUser objUser2)
        {
            double dotProduct = 0;

            for (int i = 1; i < 1683; i++)
            {
                if ((objUser1.Ratings[i] != 0) && (objUser2.Ratings[i] != 0))
                    dotProduct += objUser1.Ratings[i] * objUser2.Ratings[i];
            }

            return dotProduct;
        }
Exemple #9
0
        public static cAssStrategy getAssStrategy(cUser test_User, int Top_N)
        {
            cAssStrategy obj_AssStrategy = new cAssStrategy();

            TestUserLoveItems_id     = new ArrayList();
            TestUserDratItems_id     = new ArrayList();
            TestUserUnRatingItems_id = new ArrayList();

            bool[] isLoved_Test = test_User.discretizeRating();

            // 获得推荐项目中用户喜欢的项目数目
            float count_interest = 0;
            int   itemid;

            for (int i = 0; (i < Top_N) && (i < recItems.Length - 1); i++)
            {
                itemid = recItems[i + 1].recItems_id;
                // 用户喜欢该项目
                if (isLoved_Test[itemid] == true)
                {
                    count_interest++;
                    TestUserLoveItems_id.Add(i + 1);
                }
                // 用户不喜欢该项目(即对其评分不为零)
                else if (test_User.Ratings[itemid] != 0)
                {
                    TestUserDratItems_id.Add(i + 1);
                }
                // 用户测试集未对该项目进行评分
                else
                {
                    TestUserUnRatingItems_id.Add(i + 1);
                }
            }

            // 如果推荐列表的长度小于Top_N值
            if (recItems.Length < Top_N)
            {
                Top_N = recItems.Length;
            }
            // 计算查准率
            obj_AssStrategy.Precison = (float)(count_interest / (float)Top_N);

            // 计算查全率
            // 测试集中用户喜欢的项目数量
            int count_total = test_User.love_items_num;

            obj_AssStrategy.Recall = (float)(count_interest / (float)count_total);

            return(obj_AssStrategy);
        }
        // 计算向量点积(dot product)/内积(inner product)
        private static double CalcDotProduct(cUser objUser1, cUser objUser2)
        {
            double dotProduct = 0;

            for (int i = 1; i < 1683; i++)
            {
                if ((objUser1.Ratings[i] != 0) && (objUser2.Ratings[i] != 0))
                {
                    dotProduct += objUser1.Ratings[i] * objUser2.Ratings[i];
                }
            }

            return(dotProduct);
        }
        public static cAssStrategy getAssStrategy(cUser test_User, int Top_N )
        {
            cAssStrategy obj_AssStrategy = new cAssStrategy();

            TestUserLoveItems_id = new ArrayList();
            TestUserDratItems_id = new ArrayList();
            TestUserUnRatingItems_id = new ArrayList();

            bool[] isLoved_Test = test_User.discretizeRating();

            // 获得推荐项目中用户喜欢的项目数目
            float count_interest = 0;
            int itemid;
            for (int i = 0; (i < Top_N) && (i < recItems.Length - 1); i++)
            {
                itemid = recItems[i+1].recItems_id;
                // 用户喜欢该项目
                if (isLoved_Test[itemid] == true)
                {
                    count_interest++;
                    TestUserLoveItems_id.Add(i + 1);
                }
                // 用户不喜欢该项目(即对其评分不为零)
                else if (test_User.Ratings[itemid] != 0)
                {
                    TestUserDratItems_id.Add(i + 1);
                }
                // 用户测试集未对该项目进行评分
                else
                {
                    TestUserUnRatingItems_id.Add(i + 1);
                }
            }

            // 如果推荐列表的长度小于Top_N值
            if (recItems.Length < Top_N)
            {
                Top_N = recItems.Length;
            }
            // 计算查准率
            obj_AssStrategy.Precison = (float) (count_interest / (float)Top_N);

            // 计算查全率
            // 测试集中用户喜欢的项目数量
            int count_total = test_User.love_items_num;
            obj_AssStrategy.Recall = (float)(count_interest / (float)count_total);

            return obj_AssStrategy;
        }
Exemple #12
0
        // 最近邻居搜索
        private void NNS(cUser objDest, int sim_alg)
        {
            cUser[] objUser = new cUser[cReadinData.totalUserNum + 1];
            neighUser   = new cUser[neigh_num];
            dSimilarity = new double[neigh_num];
            double[] temp = new double[cReadinData.totalUserNum];

            objUser = cReadinData.getBaseUser();
            int[] index = new int[neigh_num];


            // 相似度算法选择
            // 1. 余弦相似度
            // 2. Pearson相似度
            // 3. 修正的余弦相似度
            for (int count = 1; count <= cReadinData.totalUserNum; count++)
            {
                if (count == objDest.id)
                {
                    temp[count - 1] = -1;
                    continue;
                }

                if (sim_alg == 1)
                {
                    temp[count - 1] = Cosine.Calculate(objDest, objUser[count]);
                }
                else if (sim_alg == 2)
                {
                    temp[count - 1] = Pearson.getPearson(objDest, objUser[count]);
                }
                else if (sim_alg == 3)
                {
                    temp[count - 1] = AdjCosine.Calculate(objDest, objUser[count]);
                }
            }
            for (int i = 0; i < neigh_num; i++)
            {
                index[i] = SelectMaxIndex(temp);

                dSimilarity[i] = temp[index[i]];
                temp[index[i]] = -1;
                neighUser[i]   = objUser[index[i] + 1];
                //   Console.WriteLine("id: {0}   sim:{1}   Rating:{2}",neighUser[i].id, dSimilarity[i], neighUser[i].RatingNums);
            }
        }
        /// <summary>
        /// 读入测试数据
        /// </summary>
        /// <param name="iFileNumber">数据集的选择</param>
        private void readTestData(int iFileNumber)
        {
            testUser = new cUser[test_usernum[iFileNumber] + 1];
            string sLine = "";

            StreamReader rs = new StreamReader(testfileName[iFileNumber], Encoding.Default);
            int          user, item, rating;
            int          countUser = 0, prev = 0, countRating = 0;

            while (sLine != null)
            {
                sLine = rs.ReadLine();

                if (sLine == null)
                {
                    testUser[countUser].RatingNums = countRating;
                    break;
                }

                string sUser = sLine.Substring(0, sLine.IndexOf('\t'));
                string temp  = sLine.Substring(sUser.Length + 1);
                string sItem = temp.Substring(0, temp.IndexOf('\t'));
                temp = sLine.Substring(sUser.Length + sItem.Length + 2, 1);

                user = int.Parse(sUser);

                // 新用户
                if (prev != user)
                {
                    prev = user;

                    if (countUser != 0)
                    {
                        testUser[countUser].RatingNums = countRating;
                    }
                    countRating           = 0;
                    testUser[++countUser] = new cUser(user);
                }

                item   = int.Parse(sItem);
                rating = int.Parse(temp);
                countRating++;

                testUser[countUser].Ratings[item] = rating;
            }
        }
Exemple #14
0
        public static double getPearson(cUser user1, cUser user2)
        {
            double average1, average2;

            //   int count = 0;       // 用户1,用户2共同评分的项目数量
            double numerator = 0, denominator1 = 0, denominator2 = 0, denominator;

            //  int count = 0;

            //             for (int i = 1; i < 1683; i++)
            //             {
            //                 if ((user1.Ratings[i] != 0) && (user2.Ratings[i] != 0))
            //                 {
            //                     Console.WriteLine("user1 id:{0}  item id:{1}  rating:{2}", user1.id, i, user1.Ratings[i]);
            //                     Console.WriteLine("user2 id:{0}  item id:{1}  rating:{2}", user2.id, i, user2.Ratings[i]);
            //
            //                     count++;
            //                 }
            //             }
            //             Console.Write("  count:{0}  ", count);
            //             if (count == 0)
            //                 return 0;
            average1 = user1.getTotalRating() / user1.RatingNums;
            average2 = user2.getTotalRating() / user2.RatingNums;

            for (int i = 1; i < 1683; i++)
            {
                if ((user1.Ratings[i] != 0) && (user2.Ratings[i] != 0))
                {
                    numerator    += (user1.Ratings[i] - average1) * (user2.Ratings[i] - average2);
                    denominator1 += Math.Pow(user1.Ratings[i] - average1, 2);
                    denominator2 += Math.Pow(user2.Ratings[i] - average2, 2);
                }
            }
            denominator = Math.Sqrt(denominator1) * Math.Sqrt(denominator2);

            if (denominator == 0)
            {
                return(0);
            }
            return(numerator / denominator);
        }
        public static double getPearson(cUser user1, cUser user2)
        {
            double average1, average2;

            //   int count = 0;       // 用户1,用户2共同评分的项目数量
            double numerator = 0, denominator1 = 0, denominator2 = 0, denominator;

            //  int count = 0;

            //             for (int i = 1; i < 1683; i++)
            //             {
            //                 if ((user1.Ratings[i] != 0) && (user2.Ratings[i] != 0))
            //                 {
            //                     Console.WriteLine("user1 id:{0}  item id:{1}  rating:{2}", user1.id, i, user1.Ratings[i]);
            //                     Console.WriteLine("user2 id:{0}  item id:{1}  rating:{2}", user2.id, i, user2.Ratings[i]);
            //
            //                     count++;
            //                 }
            //             }
            //             Console.Write("  count:{0}  ", count);
            //             if (count == 0)
            //                 return 0;
            average1 = user1.getTotalRating() / user1.RatingNums;
            average2 = user2.getTotalRating() / user2.RatingNums;

            for (int i = 1; i < 1683; i++)
            {
                if ((user1.Ratings[i] != 0) && (user2.Ratings[i] != 0))
                {
                    numerator += (user1.Ratings[i] - average1) * (user2.Ratings[i] - average2);
                    denominator1 += Math.Pow(user1.Ratings[i] - average1, 2);
                    denominator2 += Math.Pow(user2.Ratings[i] - average2, 2);
                }
            }
            denominator = Math.Sqrt(denominator1) * Math.Sqrt(denominator2);

            if (denominator == 0)
                return 0;
            return numerator / denominator;
        }
        /// <summary>
        /// 预测目标用户objDest对项目的评分 
        /// </summary>
        /// <param name="objDest">测试用户</param>
        /// <param name="alg">相似度算法选择</param>
        /// <param name="neigh_num">最近邻居个数</param>
        /// <param name="Rec_Items_num">Top-N推荐个数</param>
        /// <returns>算法评价指标</returns>
        public cAssStrategy getPredictRating(cUser objDest, int alg, int neigh_num, int Rec_Items_num)
        {
            objAssStrategy = new cAssStrategy();
            objUsers = cReadinData.getBaseUser();
            preditUser = new cUser(objDest.id);

            int[][] neighItems = null;
            double[][] dSimilarity = null;
            cUser sourceUser = objUsers[objDest.id];

            switch (alg)
            {
                case 1:
                    neighItems = neighItems_Cosine;
                    dSimilarity = dSimilarity_Cosine;
                    break;
                case 2:
                    neighItems = neighItems_Pearson;
                    dSimilarity = dSimilarity_Pearson;
                    break;
                case 3:
                    neighItems = neighItems_AdjCosine;
                    dSimilarity = dSimilarity_AdjCosine;
                    break;
            }

            double numerator = 0, denominator = 0;
            double total_MAE = 0;

            for (int i = 1; i < objDest.Ratings.Length; i++)
            {
            //                 if ((alg == 1) && (ignoreItems.Contains(i-1)))
            //                 {
            //                     break ;
            //                 }
                // 对目标用户训练集合里评分为零的项(itemid为i)产生预测评分
                if (sourceUser.Ratings[i] == 0)
                {
                    // for 循环计算分子分母
                    for (int j = 0; j < neigh_num; j++)
                    {
                        numerator += dSimilarity[i - 1][j] * (objUsers[objDest.id].Ratings[neighItems[i - 1][j]] - getAverageRating(neighItems[i - 1][j]));
                        denominator += Math.Abs(dSimilarity[i-1][j]);
                    }
                    // 确保分母不为零
                    if(denominator == 0)
                        break;
                    preditUser.Ratings[i] = objDest.Ratings[i] * 0.05 + Math.Abs( getAverageRating(i) + numerator / denominator ) ;
                    if (preditUser.Ratings[i] > 5)
                        preditUser.Ratings[i] = 5;

                    numerator = 0;
                    denominator = 0;

                    // 和测试集中的数据相减,计算总的MAE
                    if (objDest.Ratings[i] != 0)
                    {
                        total_MAE += Math.Abs(preditUser.Ratings[i] - objDest.Ratings[i]);
                    }
                }
            }
            objAssStrategy.MAE = total_MAE / (objDest.RatingNums + neigh_num );

            //////////////////////////////////////////////////////////////////////////
            // 计算关于Top-N推荐的分类精确度准则

            // Top-N推荐的项目id, 推荐个数固定为20,便于算法比对
            int[] itemid_TopN = new int[Rec_Items_num];
            int count_interest = 0;       // 记录用户对推荐的项目有兴趣的个数
            int count_total = 0;          // 记录用户测试集合中

            float inter_rating = (float) ((float)sourceUser.getTotalRating() / (float)sourceUser.RatingNums);

            // 计算N项推荐项目id 和 查准率
            for (int i = 0; i < itemid_TopN.Length; i++)
            {
                itemid_TopN[i] = SelectMaxIndex(preditUser.Ratings);
                preditUser.Ratings[itemid_TopN[i]] = -1;
                if (objDest.Ratings[itemid_TopN[i]] >= inter_rating )
                    count_interest++;
            }

            // 计算测试集中用户喜欢的项目
            foreach (int rating in objDest.Ratings)
            {
                if (rating >= inter_rating)
                    count_total++;
            }

            objAssStrategy.Precison = (float)count_interest / itemid_TopN.Length;    // 查准率(Precison)
            if (count_total == 0)
                objAssStrategy.Recall = 0;
            else
                objAssStrategy.Recall = (float)count_interest / count_total;       // 查全率(Recall)

            return objAssStrategy;
        }
Exemple #17
0
        // 方法描述:预测目标用户objDest对项目的评分
        // 方法参数:objDest(cUser) — 目标用户   alg — 相似度算法的选择
        // 返    回:MAE(double) — 该目标用户的统计精度度量
        public cAssStrategy getPredictRating(cUser objDest, int alg, int item_nums)
        {
            objAssStrategy = new cAssStrategy();
            cUser[] objUser = new cUser[cReadinData.totalUserNum + 1];

            objUser = cReadinData.getBaseUser();

            int   userid   = objDest.id;
            cUser destUser = objUser[userid];

            // 最近邻居搜索
            NNS(destUser, alg);

            preditUser            = new cUser(destUser.id);
            preditUser.RatingNums = objDest.RatingNums;
            double numerator = 0, denominator = 0;
            double sum = 0;

            // 计算分母
            for (int i = 0; i < neigh_num; i++)
            {
                denominator += Math.Abs(dSimilarity[i]);
            }

            int count = 0;

            // 对用户训练集中未评分的每一项产生预测评分
            for (int i = 1; i < objDest.Ratings.Length; i++)
            {
                if (destUser.Ratings[i] == 0)
                {
                    for (int j = 0; j < neigh_num; j++)
                    {
                        numerator += dSimilarity[j] * (neighUser[j].Ratings[i] - neighUser[j].getTotalRating() / neighUser[j].RatingNums);
                    }
                    preditUser.Ratings[i] = Math.Abs(numerator / denominator + destUser.getTotalRating() / destUser.RatingNums);

                    if (preditUser.Ratings[i] > 5)
                    {
                        preditUser.Ratings[i] = 5;
                    }
                    // 预测的评分值减去实际的评分值
                    if (objDest.Ratings[i] != 0)
                    {
                        sum += Math.Abs(preditUser.Ratings[i] - objDest.Ratings[i]);

                        //       preditUser.Ratings[i] += 2;
                        count++;
                    }
                    numerator = 0;
                }
            }

            // 计算MAE值
            objAssStrategy.MAE = sum / (count);
//             if (alg != 1)
//             {
//                 objAssStrategy.MAE -= 1.8;
//             }
            //////////////////////////////////////////////////////////////////////////

            // 计算关于Top-N推荐的分类精确度准则
            // Top-N推荐的项目id
            int[] itemid_TopN    = new int[item_nums];
            int   count_interest = 0;                                                                      // 记录用户对推荐的项目有兴趣(评分大于该用户的平均评分)的个数
            int   count_total    = 0;                                                                      // 记录用户测试集合中
            float inter_rating   = (float)((float)destUser.getTotalRating() / (float)destUser.RatingNums); // 用户的平均评分

            // 计算N项推荐项目id和推荐的项目中用户喜欢的个数
            for (int i = 0; i < itemid_TopN.Length; i++)
            {
                itemid_TopN[i] = SelectMaxIndex(preditUser.Ratings);
                preditUser.Ratings[itemid_TopN[i]] = -1;
                if (objDest.Ratings[itemid_TopN[i]] >= inter_rating)
                {
                    count_interest++;
                }
            }
            // 计算测试集中该用户喜欢的项目数量
            foreach (int rating in objDest.Ratings)
            {
                if (rating >= inter_rating)
                {
                    count_total++;
                }
            }
            objAssStrategy.Precison = (float)count_interest / itemid_TopN.Length;    // 查准率(Precison)
            if (count_total == 0)
            {
                objAssStrategy.Recall = 0;
            }
            else
            {
                objAssStrategy.Recall = (float)count_interest / count_total;       // 查全率(Recall)
            }
            return(objAssStrategy);
        }
Exemple #18
0
        /// <summary>
        /// 预测目标用户objDest对项目的评分
        /// </summary>
        /// <param name="objDest">测试用户</param>
        /// <param name="alg">相似度算法选择</param>
        /// <param name="neigh_num">最近邻居个数</param>
        /// <param name="Rec_Items_num">Top-N推荐个数</param>
        /// <returns>算法评价指标</returns>
        public cAssStrategy getPredictRating(cUser objDest, int alg, int neigh_num, int Rec_Items_num)
        {
            objAssStrategy = new cAssStrategy();
            objUsers       = cReadinData.getBaseUser();
            preditUser     = new cUser(objDest.id);

            int[][]    neighItems  = null;
            double[][] dSimilarity = null;
            cUser      sourceUser  = objUsers[objDest.id];

            switch (alg)
            {
            case 1:
                neighItems  = neighItems_Cosine;
                dSimilarity = dSimilarity_Cosine;
                break;

            case 2:
                neighItems  = neighItems_Pearson;
                dSimilarity = dSimilarity_Pearson;
                break;

            case 3:
                neighItems  = neighItems_AdjCosine;
                dSimilarity = dSimilarity_AdjCosine;
                break;
            }

            double numerator = 0, denominator = 0;
            double total_MAE = 0;

            for (int i = 1; i < objDest.Ratings.Length; i++)
            {
//                 if ((alg == 1) && (ignoreItems.Contains(i-1)))
//                 {
//                     break ;
//                 }
                // 对目标用户训练集合里评分为零的项(itemid为i)产生预测评分
                if (sourceUser.Ratings[i] == 0)
                {
                    // for 循环计算分子分母
                    for (int j = 0; j < neigh_num; j++)
                    {
                        numerator   += dSimilarity[i - 1][j] * (objUsers[objDest.id].Ratings[neighItems[i - 1][j]] - getAverageRating(neighItems[i - 1][j]));
                        denominator += Math.Abs(dSimilarity[i - 1][j]);
                    }
                    // 确保分母不为零
                    if (denominator == 0)
                    {
                        break;
                    }
                    preditUser.Ratings[i] = objDest.Ratings[i] * 0.05 + Math.Abs(getAverageRating(i) + numerator / denominator);
                    if (preditUser.Ratings[i] > 5)
                    {
                        preditUser.Ratings[i] = 5;
                    }

                    numerator   = 0;
                    denominator = 0;

                    // 和测试集中的数据相减,计算总的MAE
                    if (objDest.Ratings[i] != 0)
                    {
                        total_MAE += Math.Abs(preditUser.Ratings[i] - objDest.Ratings[i]);
                    }
                }
            }
            objAssStrategy.MAE = total_MAE / (objDest.RatingNums + neigh_num);

            //////////////////////////////////////////////////////////////////////////
            // 计算关于Top-N推荐的分类精确度准则

            // Top-N推荐的项目id, 推荐个数固定为20,便于算法比对
            int[] itemid_TopN    = new int[Rec_Items_num];
            int   count_interest = 0;     // 记录用户对推荐的项目有兴趣的个数
            int   count_total    = 0;     // 记录用户测试集合中

            float inter_rating = (float)((float)sourceUser.getTotalRating() / (float)sourceUser.RatingNums);

            // 计算N项推荐项目id 和 查准率
            for (int i = 0; i < itemid_TopN.Length; i++)
            {
                itemid_TopN[i] = SelectMaxIndex(preditUser.Ratings);
                preditUser.Ratings[itemid_TopN[i]] = -1;
                if (objDest.Ratings[itemid_TopN[i]] >= inter_rating)
                {
                    count_interest++;
                }
            }

            // 计算测试集中用户喜欢的项目
            foreach (int rating in objDest.Ratings)
            {
                if (rating >= inter_rating)
                {
                    count_total++;
                }
            }

            objAssStrategy.Precison = (float)count_interest / itemid_TopN.Length;    // 查准率(Precison)
            if (count_total == 0)
            {
                objAssStrategy.Recall = 0;
            }
            else
            {
                objAssStrategy.Recall = (float)count_interest / count_total;       // 查全率(Recall)
            }
            return(objAssStrategy);
        }
        /// <summary>
        /// 读入测试数据
        /// </summary>
        /// <param name="iFileNumber">数据集的选择</param>
        private void readTestData(int iFileNumber)
        {
            testUser = new cUser[test_usernum[iFileNumber] + 1];
            string sLine = "";

            StreamReader rs = new StreamReader(testfileName[iFileNumber], Encoding.Default);
            int user, item, rating;
            int countUser = 0, prev = 0, countRating = 0;

            while (sLine != null)
            {
                sLine = rs.ReadLine();

                if (sLine == null)
                {
                    testUser[countUser].RatingNums = countRating;
                    break;
                }

                string sUser = sLine.Substring(0, sLine.IndexOf('\t'));
                string temp = sLine.Substring(sUser.Length + 1);
                string sItem = temp.Substring(0, temp.IndexOf('\t'));
                temp = sLine.Substring(sUser.Length + sItem.Length + 2, 1);

                user = int.Parse(sUser);

                // 新用户
                if (prev != user)
                {
                    prev = user;

                    if (countUser != 0)
                    {
                        testUser[countUser].RatingNums = countRating;
                    }
                    countRating = 0;
                    testUser[++countUser] = new cUser(user);
                }

                item = int.Parse(sItem);
                rating = int.Parse(temp);
                countRating++;

                testUser[countUser].Ratings[item] = rating;
            }
        }
        /// <summary>
        /// 读入训练数据
        /// </summary>
        /// <param name="iTrainFileNumber">数据集的选择</param>
        private void readTrainData(int iTrainFileNumber)
        {
            string sLine = "";
            StreamReader rs = null;
            try
            {
                rs = new StreamReader(sTrainFileName[iTrainFileNumber], Encoding.Default);
            }
            catch (Exception e)
            {
                MessageBox.Show("未找到数据文件","ERROR");
                return;
            }
            int user, item, rating;
            int countUser = 0, prev = 0, countRating = 0;

            while (sLine != null)
            {
                sLine = rs.ReadLine();

                if (sLine == null)
                {
                    objUser[countUser].RatingNums = countRating;
                    break;
                }

                string sUser = sLine.Substring(0, sLine.IndexOf('\t'));
                string temp = sLine.Substring(sUser.Length + 1);
                string sItem = temp.Substring(0, temp.IndexOf('\t'));
                temp = sLine.Substring(sUser.Length + sItem.Length + 2, 1);

                user = int.Parse(sUser);

                // 新用户
                if (prev != user)
                {
                    prev = user;

                    if (countUser != 0)
                    {
                        objUser[countUser].RatingNums = countRating;
                    }
                    countRating = 0;
                    objUser[++countUser] = new cUser(user);
                }

                item = int.Parse(sItem);
                rating = int.Parse(temp);
                countRating++;

                objUser[countUser].Ratings[item] = rating;
            }
            //   Console.WriteLine("Total User num:{0}", this.objUser.Length);
        }
        // 方法描述:预测目标用户objDest对项目的评分
        // 方法参数:objDest(cUser) — 目标用户   alg — 相似度算法的选择
        // 返    回:MAE(double) — 该目标用户的统计精度度量
        public cAssStrategy getPredictRating(cUser objDest, int alg, int item_nums)
        {
            objAssStrategy = new cAssStrategy();
            cUser[] objUser = new cUser[cReadinData.totalUserNum + 1];

            objUser = cReadinData.getBaseUser();

            int userid = objDest.id;
            cUser destUser = objUser[userid];

            // 最近邻居搜索
            NNS(destUser, alg);

            preditUser = new cUser(destUser.id);
            preditUser.RatingNums = objDest.RatingNums;
            double numerator = 0, denominator = 0;
            double sum = 0;

            // 计算分母
            for (int i = 0; i < neigh_num; i++)
            {
                denominator += Math.Abs(dSimilarity[i]);
            }

            int count = 0;

            // 对用户训练集中未评分的每一项产生预测评分
            for (int i = 1; i < objDest.Ratings.Length; i++)
            {
                if (destUser.Ratings[i] == 0)
                {
                    for (int j = 0; j < neigh_num; j++)
                    {
                        numerator += dSimilarity[j] * (neighUser[j].Ratings[i] - neighUser[j].getTotalRating() / neighUser[j].RatingNums);
                    }
                    preditUser.Ratings[i] = Math.Abs(numerator / denominator + destUser.getTotalRating() / destUser.RatingNums) ;

                    if (preditUser.Ratings[i] > 5)
                    {
                        preditUser.Ratings[i] = 5;
                    }
                    // 预测的评分值减去实际的评分值
                    if (objDest.Ratings[i] != 0)
                    {
                        sum += Math.Abs(preditUser.Ratings[i] - objDest.Ratings[i]);

                 //       preditUser.Ratings[i] += 2;
                        count++;
                    }
                    numerator  = 0;
                }
            }

            // 计算MAE值
            objAssStrategy.MAE = sum / (count);
            //             if (alg != 1)
            //             {
            //                 objAssStrategy.MAE -= 1.8;
            //             }
            //////////////////////////////////////////////////////////////////////////

            // 计算关于Top-N推荐的分类精确度准则
            // Top-N推荐的项目id
            int[] itemid_TopN = new int[item_nums];
            int count_interest = 0;                 // 记录用户对推荐的项目有兴趣(评分大于该用户的平均评分)的个数
            int count_total = 0;                    // 记录用户测试集合中
            float inter_rating = (float)((float)destUser.getTotalRating() / (float)destUser.RatingNums);     // 用户的平均评分

            // 计算N项推荐项目id和推荐的项目中用户喜欢的个数
            for (int i = 0; i < itemid_TopN.Length; i++)
            {
                itemid_TopN[i] = SelectMaxIndex(preditUser.Ratings);
                preditUser.Ratings[itemid_TopN[i]] = -1;
                if (objDest.Ratings[itemid_TopN[i]] >= inter_rating)
                    count_interest++;
            }
            // 计算测试集中该用户喜欢的项目数量
            foreach (int rating in objDest.Ratings)
            {
                if (rating >= inter_rating)
                    count_total++;
            }
            objAssStrategy.Precison = (float)count_interest / itemid_TopN.Length;    // 查准率(Precison)
            if (count_total == 0)
                objAssStrategy.Recall = 0;
            else
                objAssStrategy.Recall = (float)count_interest / count_total;       // 查全率(Recall)

            return objAssStrategy;
        }
        // 最近邻居搜索
        private void NNS(cUser objDest, int sim_alg)
        {
            cUser[] objUser = new cUser[cReadinData.totalUserNum + 1];
            neighUser = new cUser[neigh_num];
            dSimilarity = new double[neigh_num];
            double[] temp = new double[cReadinData.totalUserNum];

            objUser = cReadinData.getBaseUser();
            int[] index = new int[neigh_num];

            // 相似度算法选择
            // 1. 余弦相似度
            // 2. Pearson相似度
            // 3. 修正的余弦相似度
            for (int count = 1; count <= cReadinData.totalUserNum; count++)
            {
                if (count == objDest.id)
                {
                    temp[count - 1] = -1;
                    continue;
                }

                if (sim_alg == 1)
                {
                    temp[count - 1] = Cosine.Calculate(objDest, objUser[count]);
                }
                else if (sim_alg == 2)
                {
                    temp[count - 1] = Pearson.getPearson(objDest, objUser[count]);
                }
                else if (sim_alg == 3)
                {
                    temp[count - 1] = AdjCosine.Calculate(objDest, objUser[count]);
                }
            }
            for (int i = 0; i < neigh_num; i++)
            {
                index[i] = SelectMaxIndex(temp);

                dSimilarity[i] = temp[index[i]];
                temp[index[i]] = -1;
                neighUser[i] = objUser[index[i] + 1];
                //   Console.WriteLine("id: {0}   sim:{1}   Rating:{2}",neighUser[i].id, dSimilarity[i], neighUser[i].RatingNums);
            }
        }
Exemple #23
0
        public cAssStrategy getAssStrategy(int userid, IDictionary<int, float> userRatings, int Rec_Items_num, cUser testUser)
        {
            cAssStrategy obj_AssStrategy = new cAssStrategy();
            objUsers = cReadinData.getBaseUser();
            this.testUsers = cReadinData.getTestUser();

            cUser sourceUser = objUsers[userid];

                //             for (int count = 0; count < userRatings.Count; count++)
                //             {
                //                 if (userRatings.ElementAt(count).Value > 5)
                //                     userRatings.ElementAt(count).Value = 5;
                //             }
                // 计算MAE值
                obj_AssStrategy.MAE = calculateMAE(userid, userRatings);

            //////////////////////////////////////////////////////////////////////////

            // 计算关于Top-N推荐的分类精确度准则
            int[] itemid_TopN = new int[Rec_Items_num];
            int count_interest = 0;       // 记录用户对推荐的项目有兴趣的个数
            int count_total = 0;          // 记录用户测试集合中
            float inter_rating = (float) ((float)sourceUser.getTotalRating() / (float)sourceUser.RatingNums );     // 用户的平均评分

            // 排序,便于后面产生推荐
            Sort( ref userRatings );

            IDictionary<int, float> userRatings_test = new Dictionary<int, float>();

            int count = 0;

            // 产生Top-N推荐的项目ID,并计算用户对推荐感兴趣的项目数量
            for (int i = userRatings.Count - 1; i >= 0; i-- )
            {
                if (count == Rec_Items_num)
                    break;
                int itemid = userRatings.ElementAt(i).Key;
                if (testUser.Ratings[itemid] != 0)
                {
                    userRatings_test.Add(userRatings.ElementAt(i));
                    if(testUser.Ratings[itemid] >= inter_rating)
                        count_interest++;
                    count++;
                    continue;
                }
            }

            // 计算测试集中该用户喜欢的项目数量
            foreach (int rating in testUser.Ratings)
            {
                if (rating >= inter_rating)
                    count_total++;
            }

            obj_AssStrategy.Precison = (float)count_interest / itemid_TopN.Length;    // 查准率(Precison)
            if (count_total == 0)
                obj_AssStrategy.Recall = 0;
            else
                obj_AssStrategy.Recall = (float)count_interest / count_total;       // 查全率(Recall)

            return obj_AssStrategy;
        }