根据Y布尔属性

时间:2018-03-14 11:02:50

标签: c# similarity information-retrieval

假设我有5个用户,每个用户有5个布尔属性,可能如下所示:

        | A   B   C   D   E
 --------------------------
 User 0 | 1   1   0   1   0
 User 1 | 0   1   0   1   0
 User 2 | 0   0   1   0   1
 User 3 | 1   1   0   0   0
 User 4 | 0   0   0   1   0

现在最好的方法是获得最常见的“真实”的前x用户列表。所以在上面的例子中,排名看起来应该是他的:

Top 1: Users 0 (most true attributes)
Top 2: Users 0 and 1 OR Users 0 and 3 (both pairs have 2 attributes in common)
Top 3: Users 0, 1 and 3
Top 4: Users 0, 1, 3 and 4
Top 5: Users 0, 1, 2, 3, 4

我知道有两个指标和距离度量来判断两个用户的相似程度,但我想要一个最相似的用户列表。我应该使用某种聚类算法吗?但是哪一个会考虑多个二进制属性以及如何实现它(最好是在C#中)?

由于我没有参加任何关于数据挖掘的课程,所以关于这个主题的文献有点压倒性,所以任何帮助都会受到高度赞赏。

1 个答案:

答案 0 :(得分:1)

User mostTrueUser = Users
        .OrderByDescending(u => (u.A?1:0) + (u.B?1:0) + (u.C?1:0) + (u.D?1:0) + (u.E?1:0))
        .First();

var groups = Users.GroupBy(u => ((u.A && mostTrueUser.A)?1:0)
                               +((u.B && mostTrueUser.B)?1:0)
                               +((u.C && mostTrueUser.C)?1:0)
                               +((u.D && mostTrueUser.D)?1:0)
                               +((u.E && mostTrueUser.E)?1:0)
                          ,u => u).OrderByDescending(g => g.Key);
foreach(var group in groups)
{
    Console.WriteLine("{0}  // following have {0} 'true' in common with {1}",
                      group.Key,
                      mostTrueUser.ID);
    foreach(var g in group)
    {
        Console.WriteLine("  " + g.ID);
    }
}

这给了我以下内容:

3   // following have 3 'true' in common with 0
  0
2   // following have 2 'true' in common with 0
  1
  3
1   // following have 1 'true' in common with 0
  4
0   // following have 0 'true' in common with 0
  2

说明

我使用u.A?1:0因此true变为1false变为0
然后,我使用true获得了大多数OrderByDescending([sum of trues])的用户 然后,GroupBy用于将所有用户与true上的mostTrueUser数量分组。

您的排名似乎有点复杂,但您可以从此开始解决它。

我写了一点调整:

public class UserRank
{
    public User UserA{get;set;}
    public User UserB{get;set;}
    public int Compare{
        get{return ((UserA.A && UserB.A)?1:0)
                  +((UserA.B && UserB.B)?1:0)
                  +((UserA.C && UserB.C)?1:0)
                  +((UserA.D && UserB.D)?1:0)
                  +((UserA.E && UserB.E)?1:0);}
    }
}

然后:

List<UserRank> userRanks = new List<UserRank>();
for(int i=0;i<Users.Count;i++)
{
    for(int j=i;j<Users.Count;j++)
    {
        userRanks.Add(new UserRank
        {
            UserA = Users[i],
            UserB = Users[j]
        });
    }
}

var groups = userRanks.GroupBy(u => u.Compare, u => u).OrderByDescending(g => g.Key);

foreach(var group in groups)
{
    Console.WriteLine("{0} in common:",group.Key);

    foreach(var u in group)
    {
        Console.WriteLine("  {0}-{1}",u.UserA.ID,u.UserB.ID);
    }
}

给了我:

3 in common:
  0-0
2 in common:
  0-1
  0-3
  1-1
  2-2
  3-3
1 in common:
  0-4
  1-3
  1-4
  4-4
0 in common:
  0-2
  1-2
  2-3
  2-4
  3-4

TutorialsPoint CodingGround permalink for testing purpose