当每个向量的元素具有不同的范围时,如何计算2个向量的余弦相似度

时间:2012-07-10 09:41:08

标签: java algorithm math

如何找到两个向量之间的余弦相似度,向量的每个元素都有不同的范围? 例如,每个向量有两个元素V = {v[0], v[1]},例如{age,height},其中age的范围是30到70,高度范围是100cm - 200 cm,两个示例向量,v1 = {20, 175}, v2 = {35,192}是给出。

我知道余弦相似度(sim)定义为sim = (v1 dot v2 ) / (|v1| * |v2|),其中dot是v1和v2之间的点积,| v |是矢量的大小。但这是基于假设向量V中的每个元素具有相同的数据范围,并且当每个元素具有不同的范围时不应用它,例如我在这里使用的情况。

我能想到的一件事是将权重向量W = {w[0],w[1]}应用于每个向量v1,并将v2应用于向量中对每个元素进行标准化。

那是

weighted_sim = ( sum (w[i] * v1[i] * v2[i]) )  / sqrt ( (sum (w[i] *v1[i]^2 ) ) * ( sum (w[i] *v2[i]^2 ) ) )

但我很难在这里找出权重向量W.

有人可以帮助我吗?非常感谢。

2 个答案:

答案 0 :(得分:1)

我只是将两个测量值归一化,使其位于[0,1]范围内。因此,标准化年龄为(real_age-30)/(70-30),标准化高度为(real_height-100)/(200-100)。我注意到您的示例向量V1的年龄为20,超出了您指定的范围。

这些计算不会为您提供可通过简单乘法应用于原始数据的权重。我首先计算归一化向量,然后计算它们之间的向量相似性。

答案 1 :(得分:1)

您可能在标准化之后,但这需要的数据多于两个输入向量。如果您希望将其中一项功能(我认为这两项功能视为两项功能)比另一项更重要/更不重要,则会应用加权。

作为一个例子,我人为地考虑了应用标准化的整个范围(以整数步长),并将您的单个示例与规范化进行比较,而没有过程(即,对数据不执行任何操作)。这是结果:

(standardization) Similarity: 0.744599          Data: (-1.12599, 0.88339), (-0.259844, 1.47232).
(  normalization) Similarity: 0.978736          Data: (0.166667, 0.75), (0.416667, 0.92).
(           none) Similarity: 0.997788          Data: (20, 175), (35, 192).

使用标准化的结果至少对我更有意义。

以下是产生上述内容的示例基本代码:

import numpy

def cosine_dist(a, b): # Similarity between a and b
    return sum(a * b) / ((sum(a ** 2) * sum(b ** 2)) ** 0.5)


age_range = [10., 70.]
height_range = [100., 200.]

# Input.
age = numpy.array([20, 35])
height = numpy.array([175, 192])

# Normalization
age_n = numpy.array(age, dtype=float)
height_n = numpy.array(height, dtype=float)
age_n = (age_n - age_range[0]) / (age_range[1] - age_range[0])
height_n = (height_n - height_range[0]) / (height_range[1] - height_range[0])

# Standardization.
all_age = numpy.array(range(*map(int, age_range)))
all_height = numpy.array(range(*map(int, height_range)))
age_s = numpy.array(age, dtype=float)
height_s = numpy.array(height, dtype=float)
age_s = (age_s - all_age.mean()) / all_age.std()
height_s = (height_s - all_height.mean()) / all_height.std()

for name, a, h in [('standardization', age_s, height_s),
        ('normalization', age_n, height_n), ('none', age, height)]:

    data = numpy.array([(a[0], h[0]), (a[1], h[1])])
    data_s = '(%g, %g), (%g, %g)' % (data[0][0], data[0][1], data[1][0], data[1][1])
    print "(%15s) Similarity: %g\t\tData: %s." % (name, cosine_dist(*data),
            data_s)