计算相似度的方法

时间:2010-06-05 19:26:36

标签: statistics social-networking data-mining pattern-recognition similarity

我正在做一个社区网站,要求我计算任何两个用户之间的相似性。每个用户都使用以下属性进行描述:

年龄,皮肤类型(油性,干性),头发类型(长,短,中),生活方式(活跃的户外爱好者,电视垃圾)等。

有谁能告诉我如何处理这个问题或者指出一些资源?

6 个答案:

答案 0 :(得分:14)

另一种计算方法(在R中)数据集中观察值之间的所有成对不相似度(距离)。原始变量可以是混合类型。通过使用Gower的一般相异系数(Gower,J.C。(1971)A general coefficient of similarity及其一些属性,Biometrics 27,857-874)来实现对名义,序数和(a)对称二进制数据的处理。如需更多信息,请查看this on page 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

如果您对分类数据的降维方法感兴趣(也是将变量排列到同构群集中的方法),请检查this

答案 1 :(得分: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 :(得分:2)

你可能应该看看

这些主题可让您的程序识别您的用户集合中的相似之处和群集,并尝试适应它们......

然后您可以了解相关用户的不同隐藏的公共群组 ...(即绿头发的用户通常不喜欢看电视..)

作为建议,请尝试使用现成的工具来实现此功能,而不是自己实现...
看看Open Directory Data Mining Projects

答案 3 :(得分:1)

实现一个简单的主观指标的三个步骤,以便在您的情况下可能正常工作的两个数据点之间存在差异:

  1. 在代表性数字变量中捕获所有变量,例如:皮肤类型(油性= -1,干燥= 1),头发类型(长= 2,短= 0,中等= 1),生活方式(活跃的户外爱好者) = 1,TV junky = -1),年龄是一个数字。
  2. 缩放所有数字范围,使它们符合您为表示差异而给予它们的相对重要性。例如:10年的年龄差异与长发和中发之间的差异以及油性和干性皮肤之间的差异大致不同。因此,年龄尺度上的10与毛发尺度上的1不同,皮肤尺度为2,因此将年龄差异缩小0.1,毛发中的差异为1,皮肤中的差异为0.5
  3. 使用适当的distance metric来组合两个人之间在不同尺度上的差异。这个数字越小,它们就越相似。我建议简单的二次差分作为你的距离函数的第一次尝试。
  4. 然后可以计算两个人之间的差异(我假设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;
    }
    

    请注意,此示例中的diff不是很好的比例,如(0..1)。它的值可以从0(无差异)到大(高差异)。此外,这种方法几乎完全不科学,它只是为了快速为您提供工作差异指标。

答案 4 :(得分:0)

查看用于计算字符串差异的算法。它与您的需求非常相似。将属性存储为位串并计算字符串之间的距离

答案 5 :(得分:0)