您的足迹:首页 > 未分类 >用C#写基于用户的协同过滤算法,推荐网站上你可能感兴趣的人

用C#写基于用户的协同过滤算法,推荐网站上你可能感兴趣的人

基于用户的协同过滤算法推荐关注的用户

 截图展示.png

简介:

基于用户的协同过滤算法很早就出现了,是推荐系统最古老的最著名的算法,1992年被提出并用于邮件系统过滤,之后很久也一直被业界广泛的使用。什么叫做基于用户的协同过滤算法呢?简单来说就是把和你在同一个兴趣圈子里的人的爱好推荐给你。比如说:你加入了一个文艺青年阅读的圈子,那么意味着你和圈子里的人都有着相同的阅读兴趣,如果你那天想看一本新书,有不知道看哪些书,那么这个圈子里的人推荐你一本《生命不能承受之轻》,你发现这本书你没有看过,而且正好还符合你的阅读口味,其实通过用户推荐物品的行为,就叫做基于用户的协同过滤算法。

 

什么时候使用推荐系统:

1.       需求的数据信息过载。

2.       没有明确的选择目标。

 

比如你选择一首好听的歌,首先新歌老歌各种风格的歌曲库十分丰富。你现在只是想听一首歌,确并不知道听那首歌,如果确切知道那首歌直接就可以通过搜索引擎选出来。如果你关注的一个朋友在听一首新出来的歌,那么把这首歌推荐给你,很有可能是你喜欢的风格。

 

推荐系统带来的巨大利益

亚马逊的前科学家Greg Linden在他的博客里说过,在他离开亚马逊的时候,亚马逊至少有20%的销售来自于推荐算法。此外亚马逊的前首席科学家Andreas Weigend在斯坦福曾经讲过一次推荐系统的课,据听他课的同学透露,亚马逊有20%~30%的销售来自于推荐系统。

就在我购买《推荐系统实践》这本书的时候,推荐系统同时推荐了另外一本相关的书,看了下简介也很感兴趣,咬牙一起买了,看这就把点击率有效的转化为购买行为了。

 

算法原理

实现基于用户的协同过滤算法主要包括两个步骤:

1.       找到与目标用户兴趣相似的用户集合

2.       找到这个集合中用户喜欢的、并且目标用户没有听说过的物品推荐给目标用户

 

首先寻找和用户兴趣相契合的用户集合,这里我们主要用到2个公式来计算两个用户的兴趣相似度。

1.       jaccard公式:

1.png

2.       余弦相似度公式:

2.png

这里N便是集合,uv分别表示两个用户的感兴趣的人或物的集合。

 

其次,根据以上公式得到用户的兴趣相似度后,UserCF算法会给用户推荐和他兴趣最相似的K个用户喜欢的物品。

如下公式计算用户u对物品i的感兴趣程度:

3.png

rvi 表示用户 v 对 i 的喜欢程度,在本例中都是为 1,在一些需要用户给予评分的推荐系统中,则要代入用户评分。


实例讲解:

本文将基于之前的博文《使用C#+Jumony开发网络爬虫并对数据做相关分析

使用爬虫爬取的 伯乐在线 网站的用户信息实现。

 

数据实体:

1.       用户,使用网站主页URL地址作为唯一标识

    例如:用户:唐小娟,主页URL地址为:http://www.jobbole.com/members/ tangxiaojuan/

2.       该用户的关注人,目前爬虫只取主页有的关注用户,其他更多关注用户没有获取。

 

实现过程:

1.       初始化用户数据加载,并输入相关的参数。

    源码如下:

   Console.WriteLine("初始化数据");
            MyUsers = new List<User>();
            InitUser();
            Console.WriteLine("数据准备完毕...");
            Console.WriteLine("请输入推荐人数:");
            int needCount = Convert.ToInt32(Console.ReadLine());
            Console.WriteLine("请输入用户名,URL地址名");
            string nameUrl = Console.ReadLine();
            nameUrl = nameUrl.TrimEnd('/');
            User user = MyUsers.Where(s => s.Url.Contains(nameUrl)).FirstOrDefault();
            if (user == null)
            {
                Console.WriteLine("未查到此用户!");
                Console.ReadLine();
                return;
            }

 

2.       计算所有用户和输入用户的相似度,并排除掉相似度等于0的用户。

    在本次实例代码中采取的是Jaccard公式来计算相似度的。

    源码如下:

 

    int writeInId = user.Id;//准备推荐人
            //计算所有用户和输入用户的相似度,并排除掉相似度等于0的用户
            List<UserSorce> userSorces = new List<UserSorce>();
            foreach (var item in MyUsers)
            {
                if (item.Id == writeInId)
                    continue;
                UserSorce userSorce = new UserSorce();
                //使用Jaccard公式计算兴趣相似度
                double numerator = user.Interest.Intersect(item.Interest).Count();
                //排除交集等于0的
                if (numerator <= 0)
                    continue;
                double denominator = user.Interest.Union(item.Interest).Count();
                if (denominator == 0)
                    continue;
                double mark = numerator / denominator;

                userSorce.Id = item.Id;
                userSorce.Name = item.Name;
                userSorce.Url = item.Url;
                userSorce.Interest = item.Interest;
                userSorce.Sorce = mark;
                userSorces.Add(userSorce);
            }
            if (userSorces.Count <= 0)
                Console.WriteLine("无合适的推荐");

            userSorces = userSorces.OrderByDescending(s => s.Sorce).ToList();

3.       选取n个相似度最高的用户,分别计算出用户的感兴趣程度,按大小排序输出。

    源码如下:

   //选择最相似的n个用户
            Console.WriteLine("==========================");
            Console.WriteLine("与该用户关注最相似的" + needCount + "用户如下:");
            List<string> interests = new List<string>();
            for (int i = 0; i < needCount; i++)
            {
                UserSorce u = userSorces[i];
                Console.WriteLine("No." + (i + 1) + " 相似度[" + userSorces[i].Sorce.ToString("F4") + "]" + ":");
                Console.WriteLine(u.Name + "(" + u.Url + ")" + Environment.NewLine);

                if (u.Interest.Count() == 0)
                    continue;
                if (interests.Count() == 0)
                    interests = u.Interest;
                else
                    interests = interests.Union(u.Interest).ToList();
            }
            Console.WriteLine("==========================");

            //已经关注的用户
            List<string> IsFollowerUsers = user.Interest;
            //加上用户本身
            IsFollowerUsers.Add(user.Url);
            //所有相似度最高的用户关注的人
            List<string> exceptInterests = interests.Except(IsFollowerUsers).ToList();

            if (exceptInterests.Count <= 0)
                Console.WriteLine("无法推荐感兴趣的人!");

            List<InterestStar> stars = new List<InterestStar>();
            foreach (var interest in exceptInterests)
            {
                double value = 0;
                double depth = 1;//感兴趣的程度
                //推荐人
                string recommendUser = String.Empty;
                for (int i = 0; i < needCount; i++)
                {
                    User u = new User();
                    u = MyUsers.Where(s => s.Id == userSorces[i].Id).FirstOrDefault();
                    if (u.Interest.Contains(interest))
                    {
                        recommendUser += "[" + u.Name + "]";
                        double sorce = userSorces.Where(s => s.Id == u.Id).FirstOrDefault().Sorce * depth;
                        value += sorce;
                    }
                }

                InterestStar star = new InterestStar();
                var mUser = MyUsers.Where(s => s.Url.Contains(interest)).FirstOrDefault();
                if (mUser == null)
                    star.Name = interest;
                else
                    star.Name = mUser.Name + "(" + mUser.Url + ")";
                star.StarSorce = value;
                star.RecommendUser = recommendUser;
                stars.Add(star);
            }
            stars = stars.OrderByDescending(s => s.StarSorce).ToList();


            int starIndex = 1;
            Console.WriteLine(Environment.NewLine + "==========================");
            Console.WriteLine("推荐用户感兴趣的人:");
            foreach (var item in stars)
            {
                if (starIndex > needCount)
                    break;
                Console.WriteLine("No." + (starIndex++) + " 感兴趣程度[" + item.StarSorce.ToString("F4") + "]" + ":");
                Console.WriteLine("感兴趣的人:" + item.Name);
                Console.WriteLine("推荐的人有:" + item.RecommendUser + Environment.NewLine);
            }
            Console.WriteLine("==========================");
            Console.WriteLine("结束");
            Console.ReadKey();

 测试结果如第一张图所示。

GitHub项目地址:https://github.com/zuiyuewentian/Recommend.git

注:本文参考项亮编著的《推荐系统实践》一书。

本博客所有文章如无特别注明均为原创。作者:cc复制或转载请以超链接形式注明转自 我的博客
原文地址《用C#写基于用户的协同过滤算法,推荐网站上你可能感兴趣的人

相关推荐

发表评论

路人甲 表情
Ctrl+Enter快速提交

网友评论(0)