Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/397.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当每个向量的元素具有不同的范围时,如何计算两个向量的余弦相似性_Java_Algorithm_Math - Fatal编程技术网

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

Java 当每个向量的元素具有不同的范围时,如何计算两个向量的余弦相似性,java,algorithm,math,Java,Algorithm,Math,如何找到两个向量之间的余弦相似性,并且向量的每个元素都有不同的范围? 例如,每个向量有两个元素,V={V[0],V[1]},例如{age,height},其中年龄范围从30到70,高度范围从100cm到200cm,给出了两个示例向量,v1={20,175},v2={35192} 我知道余弦相似性(sim)被定义为sim=(v1点v2)/(| v1 |*| v2 |),其中点是v1和v2之间的点积,| v |是向量的大小。但这是基于向量V中的每个元素都有相同的数据范围的假设,当每个元素都有不同的范

如何找到两个向量之间的余弦相似性,并且向量的每个元素都有不同的范围? 例如,每个向量有两个元素,
V={V[0],V[1]}
,例如{age,height},其中年龄范围从30到70,高度范围从100cm到200cm,给出了两个示例向量,
v1={20,175},v2={35192}

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

我能想到的一件事是对每个向量v1和v2应用权重向量
W={W[0],W[1]}
,以规范化向量中的每个元素

就是

weighted_sim = ( sum (w[i] * v1[i] * v2[i]) )  / sqrt ( (sum (w[i] *v1[i]^2 ) ) * ( sum (w[i] *v2[i]^2 ) ) )
但是我很难计算出这里的权重向量W


有人能帮我吗?非常感谢。

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


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

标准化后可能需要更多的数据,而不仅仅是两个输入向量。当您希望赋予其中一个特性(我将其视为两个特性)比另一个特性更高/更低的重要性时,将应用权重

例如,我人为地考虑了应用标准化的整个范围(以整数步为单位),并将您的单个示例与标准化和无过程(即,不处理数据)进行了比较。结果是:

(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)

您是否可以简单地将两个测量值归一化,使其位于范围
[0,1]
?所以正常化年龄应该是
(真实年龄-30)/(70-30)
?当然,这不是简单的乘法“权重”;我先计算归一化向量,然后计算向量相似度。谢谢你的回答,但归一化取决于数据分布。比如说,如果年龄在30-40岁之间呈线性分布,那么你提到的线性归一化就行了,否则就会产生额外的问题。哦,好吧,你需要比我当时能提供的更聪明的答案。在这方面,你将通过缩放一个或另一个维度或两个维度来有效地缩放一个维度,虽然这会改变你的sim结果,但不会改变它的一些基本点,例如,如果它在之前是1,那么它将在之后是1。同样,如果sim1>sim2在之前,那么它将在之后。我不知道你以后用你的sim卡做什么,但你可能会发现这没什么大不了的……谢谢你,克里斯。我打算将余弦相似性和欧氏距离以加权形式组合在一起,以测量两个向量之间的差异。欧几里德距离给出的是幅度差,而不是角度差。余弦距离在这里有相反的结果。所以我打算在这里以距离度量的加权形式将两者结合起来。谢谢你的回答,马克。另外,因为余弦相似性给出了两个向量之间的角度差,而欧几里德距离给出了两个向量之间的幅度差,这里。我们有没有办法将余弦距离和欧几里德距离以加权形式结合在一起来表示最终的距离度量。谢谢。我不知道有什么广泛使用的方法可以像你所希望的那样组合距离度量,我希望你能想出一些特别的方法,比我更好地满足你的需求。