计算相似度的方法

Posted

技术标签:

【中文标题】计算相似度的方法【英文标题】:Ways to calculate similarity 【发布时间】:2011-02-28 05:34:57 【问题描述】:

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

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

谁能告诉我如何解决这个问题或向我指出一些资源?

【问题讨论】:

相关:***.com/questions/3007790/finding-the-closest-match/… 【参考方案1】:

另一种计算(在R 中)数据集中观察值之间的所有成对差异(距离)的方法。原始变量可能是混合类型。通过使用 Gower 的一般相异系数(Gower, J. C. (1971) A general coefficient ofsimilarity and its some properties, 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

【讨论】:

“Gower's distance” is chosen by metric "gower" or automatically if some columns of x are not numeric (?cluster::daisy) 所以你不必通过metric - 这很混乱。【参考方案2】:

你应该阅读这两个主题。

Most popular clustering algorithm k - means

And similarity matrix are essential in clustering

【讨论】:

【参考方案3】:

三个步骤可实现两个数据点之间差异的简单主观指标,这可能适用于您的情况:

    将所有变量捕获在一个具有代表性的数值变量中,例如:皮肤类型(油性=-1,干性=1),头发类型(长=2,短=0,中=1),生活方式(活跃的户外爱好者=1,电视迷=-1),年龄是一个数字。 缩放所有数字范围,使其符合您为指示差异而赋予它们的相对重要性。例如:10岁的年龄差,就跟长发和中发的差距,油性皮肤和干性皮肤的差距一样大。因此,年龄尺度上的 10 与头发尺度上的 1 与皮肤尺度上的 2 一样不同,因此将年龄差异缩放 0.1,将头发缩放 1,将皮肤缩放 0.5 使用适当的distance metric 将两个人在不同尺度上的差异组合成一个整体差异。这个数字越小,它们就越相似。我建议将简单的二次差分作为距离函数的第一次尝试。

然后可以计算两个人之间的差异(我假设 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】:

你应该看看

Data Mining 和 Data Warehousing(基本) Machine Learning(额外) Artificial Neural Networks(尤其是SOM) Pattern Recognition(相关)

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

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

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

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

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

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)

【讨论】:

以上是关于计算相似度的方法的主要内容,如果未能解决你的问题,请参考以下文章

基于关联计算表中行之间相似度的最佳方法是啥?

在给定稀疏矩阵数据的情况下,Python 中计算余弦相似度的最快方法是啥?

计算两个数组之间余弦相似度的正确方法?

语义相似度相关文章链接

计算两张图片相似度的方法总结

计算图像相似度的算法都有哪些