推荐功能的两种算法
不过具体的不一样,但是其原理性的大概有以下几种算法。专门研究算法的人写的太深奥了,全部都是数学术语,太难懂了,我还是以自己的理解来说明下吧。
1、Apriori算法
Apriori算法是很复杂的,基本思想如下:
首先找出所有的已收集到的集合,即根据操作记录的集合。然后由这个集合产生强关联规则。然后使用第1步的集合产生期望的规则,产生只包含集合的项的所有规 则,其中每一条规则的右部只有一项,这里采用的是中规则的定义。一旦这些规则被生成,那么只有那些大于用户给定的最小可信度的规则才被留下来。为了生成所 有频集,使用了递推的方法。
我理解的基本步骤如下。
基本步骤是
a、根据操作收集对象的属性;
b、根据已收集的属性为条件,从包含所有数据的库中搜索与之相关的对象;
c、按照一定的规则过滤,剩下的向用户推荐。
举例来说,例如在淘宝买东西,用户买了手机,电脑,衣服等,每买一件都记录下来,作为推荐的依据;那么如何推荐呢,手机和电脑属于数码类,那么推荐就可以 推荐相机等数码产品,同时,还可以推荐其它品牌的手机或电脑。根据衣服推荐亦相同。当然了,这只是很简单的推荐,不一定能对用户的心思。要想做准确的推荐 在每一步中都要进行处理。
2、Slope One算法
使用基于Slope One算法的推荐需要以下数据:
1. 有一组用户
2. 有一组Items(文章, 商品等)
3. 用户会对其中某些项目打分(Rating)表达他们的喜好
Slope One算法要解决的问题是, 对某个用户, 已知道他对其中一些Item的Rating了, 向他推荐一些他还没有Rating的Items, 以增加销售机会. :-)
一个推荐系统的实现包括以下三步:
1. 计算出任意两个Item之间Rating的差值
2. 输入某个用户的Rating记录, 推算出对其它Items的可能Rating值
3. 根据Rating的值排序, 给出Top Items;
第一步:例如我们有三个用户和4个Items, 用户打分的情况如下表.
Ratings User1 User2 User3 Item1 5 4 4 Item2 4 5 4 Item3 4 3 N/A Item4 N/A 5 5
在第一步中我们的工作就是计算出Item之间两两的打分之差, 也就是使说计算出以下矩阵:
Item1 Item2 Item3 Item4 Item1 N/A 0/3 2/2 -2/2 Item2 0/3 N/A 2/2 -1/2 Item3 -2/2 -2/2 N/A -2/1 Item4 2/2 1/2 2/1 N/A
考虑到加权算法, 还要记录有多少人对这两项打了分(Freq), 我们先定义一个结构来保存Rating:
public class Rating { public float Value { get; set; } public int Freq { get; set; } public float AverageValue { get {return Value / Freq;} } }
用一个Dictionary来保存这个结果矩阵:
public class RatingDifferenceCollection : Dictionary<string, Rating> { private string GetKey(int Item1Id, int Item2Id) { return Item1Id + "/" + Item2Id; } public bool Contains(int Item1Id, int Item2Id) { return this.Keys.Contains<string>(GetKey(Item1Id, Item2Id)); } public Rating this[int Item1Id, int Item2Id] { get { return this[this.GetKey(Item1Id, Item2Id)]; } set { this[this.GetKey(Item1Id, Item2Id)] = value; } } }
接下来我们来实现SlopeOne类. 首先创建一个RatingDifferenceCollection来保存矩阵, 还要创建HashSet来保持系统中总共有哪些Items:
public class SlopeOne { public RatingDifferenceCollection _DiffMarix = new RatingDifferenceCollection(); // The dictionary to keep the diff matrix public HashSet<int> _Items = new HashSet<int>(); // Tracking how many items totally 方法AddUserRatings接收一个用户的打分记录(Item-Rating): public void AddUserRatings(IDictionary<int, float> userRatings) AddUserRatings中有两重循环, 外层循环遍历输入中的所有Item, 内层循环再遍历一次, 计算出一对Item之间Rating的差存入_DiffMarix, 记得Freq加1, 以记录我们又碰到这一对Items一次: Rating ratingDiff = _DiffMarix[item1Id, item2Id]; ratingDiff.Value += item1Rating - item2Rating; ratingDiff.Freq += 1; 对每个用户调用AddUserRatings后, 建立起矩阵. 但我们的矩阵是以表的形式保存: Rating Dif Freq Item1-2 0 3 Item1-3 1 2 Item2-1 0 3 Item2-3 1 2 Item3-1 -1 2 Item3-2 -1 2 Item1-4 -1 2 Item2-4 -0.5 2 Item3-4 -2 1 Item4-1 1 2 Item4-2 0.5 2 Item4-3 2 1 第二步:输入某个用户的Rating记录, 推算出对其它Items的可能Rating值: public IDictionary<int, float> Predict(IDictionary<int, float> userRatings) 也是两重循环, 外层循环遍历_Items中所有的Items; 内层遍历userRatings, 用此用户的ratings结合第一步得到的矩阵, 推算此用户对系统中每个项目的Rating: Rating itemRating = new Rating(); // Prediction of this user"s rating ... Rating diff = _DiffMarix[itemId, inputItemId]: itemRating.Value += diff.Freq * (diff.AverageValue + userRating.Value); itemRating.Freq += diff.Freq; 第三步:得到用户的Rating预测后,就可以按rating排序, 向用户推荐了. 测试一下: Dictionary<int, float> userRating userRating = new Dictionary<int, float>(); userRating.Add(1, 5); userRating.Add(3, 4); IDictionary<int, float> Predictions = test.Predict(userRating); foreach (var rating in Predictions) { Console.WriteLine("Item " + rating.Key + " Rating: " + rating.Value); } 输出: Item 2 Rating: 5 Item 4 Rating: 6 改进: 观察之前产生的矩阵可以发现, 其中有很多浪费的空间; 例如: 对角线上永远是不会有值的. 因为我们是用线性表保存矩阵值, 已经避免了这个问题; 对角线下方的值和对角线上方的值非常对称,下方的值等于上方的值乘以-1; 在数据量很大的时候是很大的浪费. 我们可以通过修改RatingDifferenceCollection来完善. 可以修改GetKey方法, 用Item Pair来作为Key: private string GetKey(int Item1Id, int Item2Id) { return (Item1Id < Item2Id) ? Item1Id + "/" + Item2Id : Item2Id + "/" + Item1Id ;; }
C#实现代码:http://download.csdn.net/detail/yysyangyangyangshan/4097454
转自:http://blog.csdn.net/yysyangyangyangshan/article/details/7303183