推薦功能的兩種算法
最近做了一個類似淘寶的根據用戶的操作,判斷出用戶對哪些產品感興趣,并按照一定關系推薦給用戶其它產品。查詢了一些資料,結果發現時下,很多地方都用到
了推薦,淘寶,優酷,迅雷等等,有時候確實讓人稱心如意,推薦的產品非常和你的胃口,不過也有時推薦的讓你莫名其妙。其實推薦的算法有很多種,而且不一定
有固定的模式,它會根據產品的特性,推薦的目的,以及其它方面的要求而不同。
不過具體的不一樣,但是其原理性的大概有以下幾種算法。專門研究算法的人寫的太深奧了,全部都是數學術語,太難懂了,我還是以自己的理解來說明下吧。
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;}
}
} </pre><br />
</div>
用一個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; }
}
} </pre><br />
</div>
接下來我們來實現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 ;;
} </pre> <p>C#實現代碼:<a href="/misc/goto?guid=5033828204671719905" target="_blank" target="_blank">http://download.csdn.net/detail/yysyangyangyangshan/4097454</a></p>
轉自:http://blog.csdn.net/yysyangyangyangshan/article/details/7303183
本文由用戶 openkk 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!