计算相似度的方法

17

我正在开发一个社区网站,需要计算任意两个用户之间的相似度。每个用户都有以下属性:

年龄、皮肤类型(油性、干性)、发型(长发、短发、中等长度)、生活方式(热爱户外运动、电视迷)等。

请问有没有人能告诉我如何解决这个问题,或者指向一些资源?


2
相关链接:https://dev59.com/oE7Sa4cB1Zd3GeqP2lRw#3007816 - Betamoo
6个回答

15
另一种计算(在R中)数据集中观测值之间所有成对差异(距离)的方法。原始变量可以是混合类型。通过使用Gower的一般不相似系数(Gower, J. C.(1971)相似性的一般系数及其某些性质,生物统计学27,857-874),可以处理名义、序数和(a)对称二进制数据。欲了解更多,请查看此处第47页。如果x包含任何这些数据类型的列,则将使用Gower系数作为度量标准。
例如:
x1 <- factor(c(10, 12, 25, 14, 29))
x2 <- factor(c("oily", "dry", "dry", "dry", "oily"))
x3 <- factor(c("medium", "short", "medium", "medium", "long"))
x4 <- factor(c("active outdoor lover", "TV junky", "TV junky", "active outdoor lover", "TV junky"))
x <- cbind(x1,x2,x3,x4)

library(cluster)
daisy(x, metric = "euclidean")

你将获得:

Dissimilarities :
         1        2        3        4
2 2.000000                           
3 3.316625 2.236068                  
4 2.236068 1.732051 1.414214         
5 4.242641 3.741657 1.732051 2.645751

如果您对用于分类数据降维的方法(也是将变量排列成同质群集的方式)感兴趣,请查看此处链接


1
如果x的某些列不是数字,则会选择度量标准“gower”的“Gower's distance”,否则会自动选择。这意味着您不必传递“metric”参数,但这可能会让事情变得更加混乱。(?cluster::daisy) - Marcin

3

给每个属性分配适当的权重,并添加值之间的差异。

enum SkinType
    Dry, Medium, Oily

enum HairLength
    Bald, Short, Medium, Long

UserDifference(user1, user2)
    total := 0
    total += abs(user1.Age - user2.Age) * 0.1
    total += abs((int)user1.Skin - (int)user2.Skin) * 0.5
    total += abs((int)user1.Hair - (int)user2.Hair) * 0.8
    # etc...
    return total

如果你真正需要相似度而不是差异性,可以使用1 / UserDifference(a, b)

2
您可能需要查看以下内容: 这些主题将使您的程序能够识别用户集合中的相似之处和聚类,并尝试适应它们...
然后,您可以了解到不同的隐藏共同群体...(例如,有绿色头发的用户通常不喜欢看电视...)
作为一条建议,尽量使用已经实现好的工具来实现这个功能,而不是自己去实现...请看Open Directory Data Mining Projects

1

三个步骤来实现一个简单的主观度量,用于比较两个数据点之间的差异,这在您的情况下可能非常有效:

  1. 将所有变量捕获到一个代表性数字变量中,例如:皮肤类型(油性=-1,干性=1),发型(长=2,短=0,中等=1),生活方式(积极户外爱好者=1,电视迷=-1),年龄是一个数字。
  2. 缩放所有数字范围,使它们适合您为指示差异赋予的相对重要性。例如:10岁的年龄差异与长发和中等发型之间的差异以及油性和干性皮肤之间的差异大约相同。因此,年龄尺度上的10与头发尺度上的1和皮肤尺度上的2一样不同,因此将年龄差异按0.1缩放,头发差异按1缩放,皮肤差异按0.5缩放。
  3. 使用适当的距离度量将两个人在各种尺度上的差异组合成一个总体差异。这个数字越小,他们就越相似。我建议首先尝试使用简单的二次差异作为距离函数。

那么两个人之间的差异可以通过以下方式计算(我假设Person.age,.skin,.hair等已经完成了步骤1并且是数字):

double Difference(Person p1, Person p2) {

    double agescale=0.1;
    double skinscale=0.5;
    double hairscale=1;
    double lifestylescale=1;

    double agediff = (p1.age-p2.age)*agescale;
    double skindiff = (p1.skin-p2.skin)*skinscale;
    double hairdiff = (p1.hair-p2.hair)*hairscale;
    double lifestylediff = (p1.lifestyle-p2.lifestyle)*lifestylescale;

    double diff = sqrt(agediff^2 + skindiff^2 + hairdiff^2 + lifestylediff^2);
    return diff;
}

请注意,此示例中的差异不是像(0..1)这样的良好比例。它的值可以从0(没有差异)到某些大数值(高差异)范围内。此外,此方法几乎完全不科学,只是为了快速提供工作差异度量而设计的。

0

看看计算字符串差异的算法。它非常类似于您所需的内容。将您的属性存储为位字符串,并计算字符串之间的距离。



网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接