根据 Y 布尔属性查找前 X 个最相似的用户
Find Top X most similar users, based on Y boolean attributes
假设我有 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
现在什么是获得具有最多 "trues" 共同点的前 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# 中)?
由于我没有学过任何 类 数据挖掘方面的知识,所以关于这个主题的文献有点多,所以非常感谢任何帮助。
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
变成了 1
而 false
变成了 0
.
然后,我使用 OrderByDescending([sum of trues])
.
获得了最多 true
的用户
然后 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
假设我有 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
现在什么是获得具有最多 "trues" 共同点的前 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# 中)?
由于我没有学过任何 类 数据挖掘方面的知识,所以关于这个主题的文献有点多,所以非常感谢任何帮助。
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
变成了 1
而 false
变成了 0
.
然后,我使用 OrderByDescending([sum of trues])
.
获得了最多 true
的用户
然后 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