C# Implement of Slope One (C#版Slope One)

http://www.cnblogs.com/kuber/articles/SlopeOne_CSharp.html

Here's the source code of my C# implementation of Weighted Slope One. Tested on .net 3.5; The instruction in Chinese can be find here and here.
Reference:
Tutorial about how to implement Slope One in Python
Slope One Predictors for Online Rating-Based Collaborative Filtering
Recommender Systems: Slope One

 

ContractedBlock.gif ExpandedBlockStart.gif Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SlopeOne
{
    
public class Rating
    {
        
public float Value { getset; }
        
public int Freq { getset; }

        
public float AverageValue
        {
            
get { return Value / Freq; }
        }
    }

    
public class RatingDifferenceCollection : Dictionary<string, Rating>
    {
        
private string GetKey(int Item1Id, int Item2Id)
        {
            
return (Item1Id < Item2Id) ? Item1Id + "/" + Item2Id : Item2Id + "/" + Item1Id ;
        }

        
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; }
        }
    }

     
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

        
public void AddUserRatings(IDictionary<intfloat> userRatings)
        {
            
foreach (var item1 in userRatings)
            {
                
int item1Id = item1.Key;
                
float item1Rating = item1.Value;
                _Items.Add(item1.Key);

                
foreach (var item2 in userRatings)
                {
                    
if (item2.Key <= item1Id) continue// Eliminate redundancy
                    int item2Id = item2.Key;
                    
float item2Rating = item2.Value;

                    Rating ratingDiff;
                    
if (_DiffMarix.Contains(item1Id, item2Id))
                    {
                        ratingDiff 
= _DiffMarix[item1Id, item2Id];
                    }
                    
else
                    {
                        ratingDiff 
= new Rating();
                        _DiffMarix[item1Id, item2Id] 
= ratingDiff;
                    }

                    ratingDiff.Value 
+= item1Rating - item2Rating;
                    ratingDiff.Freq 
+= 1;
                }
            }
        }

        
// Input ratings of all users
        public void AddUerRatings(IList<IDictionary<intfloat>> Ratings)
        {
            
foreach(var userRatings in Ratings)
            {
                AddUserRatings(userRatings);
            }
        }

        
public IDictionary<intfloat> Predict(IDictionary<intfloat> userRatings)
        {
            Dictionary
<intfloat> Predictions = new Dictionary<intfloat>();
            
foreach (var itemId in this._Items)
            {
                
if (userRatings.Keys.Contains(itemId))    continue// User has rated this item, just skip it

                Rating itemRating 
= new Rating();

                
foreach (var userRating in userRatings)
                {
                    
if (userRating.Key == itemId) continue;
                    
int inputItemId = userRating.Key;
                    
if (_DiffMarix.Contains(itemId, inputItemId))
                    {
                        Rating diff 
= _DiffMarix[itemId, inputItemId];
                        itemRating.Value 
+= diff.Freq * (userRating.Value + diff.AverageValue * ((itemId < inputItemId) ? 1 : -1));
                        itemRating.Freq 
+= diff.Freq;
                    }
                }
                Predictions.Add(itemId, itemRating.AverageValue);                
            }
            
return Predictions;
        }

        
public static void Test()
        {
            SlopeOne test 
= new SlopeOne();

            Dictionary
<intfloat> userRating = new Dictionary<intfloat>();
            userRating.Add(
15);
            userRating.Add(
24);
            userRating.Add(
34);
            test.AddUserRatings(userRating);

            userRating 
= new Dictionary<intfloat>();
            userRating.Add(
14);
            userRating.Add(
25);
            userRating.Add(
33);
            userRating.Add(
45);
            test.AddUserRatings(userRating);

            userRating 
= new Dictionary<intfloat>();
            userRating.Add(
14);
            userRating.Add(
24);
            userRating.Add(
45);
            test.AddUserRatings(userRating);

            userRating 
= new Dictionary<intfloat>();
            userRating.Add(
15);
            userRating.Add(
34);

            IDictionary
<intfloat> Predictions = test.Predict(userRating);
            
foreach (var rating in Predictions)
            {
                Console.WriteLine(
"Item " + rating.Key + " Rating: " + rating.Value);
            }
        }
    }
}
posted on 2009-03-02 17:48 djlzxzy 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/djlzxzy/archive/2009/03/02/1401683.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值