计算两个配置文件之间的相似性以获得共同特征的数量
calculating similarity between two profiles for number of common features
我正在处理社交网络配置文件的聚类问题,每个配置文件文档都由配置文件描述中 'term of interest occurs' 的次数表示。为了有效地进行聚类,我试图在两个配置文件之间找到正确的相似性度量(或距离函数)。
所以假设我有以下 table 个配置文件
basketball cricket python
profile1 4 2 1
profile2 2 1 3
profile3 2 1 0
现在,通过计算欧氏距离,我得到
distance (profile1,profile2) = 3
distance (profile2,profile3) = 3
distance (profile3,profile1) = 2.45
现在,这很好,但是我想到了两个问题
这里我们忽略了一些共同的特征,例如,即使配置文件 1 和配置文件 3 最接近,根据人类的直觉,配置文件 1 和配置文件 2 至少在所有三个兴趣方面都有一些价值 - 篮球, cricket 和 python,因此这两个配置文件可能比配置文件 1 和配置文件 3 更相似,其中一个配置文件(配置文件 3)没有在配置文件中提及 python。我也不希望只计算距离的相似特征,这肯定会产生错误的结果。
我的第一个问题 - 有什么方法可以通过任何既定的方式来适应这种直觉吗?
我的第二个问题 - 某些个人资料作者可能比其他作者更冗长,如何调整?因为有 4 次 python 出现的详细作者可能与出现 2 次 python.
的不那么冗长的作者相同
我没能为这个问题想出好的标题。很抱歉,如果它混淆。
首先,像您已经做的那样计算您的配置文件。然后关键的一步将是某种正常化。您可以将数字除以它们的总数,以便数字总和为 1,或者您可以将它们除以欧几里得范数,以便它们的欧几里得范数为 1。
例如,使用总和归一化,第一个配置文件将变为(四舍五入)
0.57, 0.29, 0.14
并使用欧几里得归一化,它会变成
0.87, 0.44, 0.22
这将确保所有配置文件都在相同的数字范围内表示,并将处理 "overly verbose profile author"。
下面是一个示例 IPython 会话,它显示了如何按行总和对行进行归一化以及如何计算归一化行之间的欧氏距离。您会看到在规范化之后,配置文件 1 和 3 靠得更近了,正如您所期望的那样。
In [22]: p = array([[4,2,1],[2,1,3],[2,1,0]])
In [23]: p
Out[23]:
array([[4, 2, 1],
[2, 1, 3],
[2, 1, 0]])
In [24]: p = p / p.sum(axis=1)[:,newaxis]
In [25]: p
Out[25]:
array([[ 0.57142857, 0.28571429, 0.14285714],
[ 0.33333333, 0.16666667, 0.5 ],
[ 0.66666667, 0.33333333, 0. ]])
In [26]: p.sum(axis=1)
Out[26]: array([ 1., 1., 1.])
In [27]: norm(p[0] - p[1]) # distance 1-2
Out[27]: 0.44543540318737401
In [28]: norm(p[0] - p[2]) # distance 1-3
Out[28]: 0.17817416127494959
In [29]: norm(p[1] - p[2]) # distance 2-3
Out[29]: 0.62360956446232352
最后,如果您想更加重视配置文件是否完全提及兴趣而不是提及频率,您可以在规范化之前执行额外的步骤:只需计算 pow(x, alpha)
对于配置文件向量的每个元素 x
,其中 alpha
是一个介于 0 和 1 之间的参数。这里,1 表示标准线性加权,如前所述,当您使 alpha 接近 0 时,表示仅提及兴趣很重要,而不是频率。例如,使用 alpha = 0.5
(取配置文件的平方根),我们得到:
In [32]: p = array([[4,2,1],[2,1,3],[2,1,0]])
In [33]: p = sqrt(p)
In [34]: p
Out[34]:
array([[ 2. , 1.41421356, 1. ],
[ 1.41421356, 1. , 1.73205081],
[ 1.41421356, 1. , 0. ]])
In [35]: p = p / p.sum(axis=1)[:,newaxis]
In [37]: norm(p[0] - p[1]) # distance 1-2
Out[37]: 0.2353133053319465
In [38]: norm(p[0] - p[2]) # distance 1-3
Out[38]: 0.27881275777438091
In [39]: norm(p[1] - p[2]) # distance 2-3
Out[39]: 0.51412606310632747
现在配置文件 1 和 2 是最接近的匹配项,因为我们更加强调他们都提到了 Python 这一事实,而不是他们提到它的频率。
我正在处理社交网络配置文件的聚类问题,每个配置文件文档都由配置文件描述中 'term of interest occurs' 的次数表示。为了有效地进行聚类,我试图在两个配置文件之间找到正确的相似性度量(或距离函数)。
所以假设我有以下 table 个配置文件
basketball cricket python
profile1 4 2 1
profile2 2 1 3
profile3 2 1 0
现在,通过计算欧氏距离,我得到
distance (profile1,profile2) = 3
distance (profile2,profile3) = 3
distance (profile3,profile1) = 2.45
现在,这很好,但是我想到了两个问题
这里我们忽略了一些共同的特征,例如,即使配置文件 1 和配置文件 3 最接近,根据人类的直觉,配置文件 1 和配置文件 2 至少在所有三个兴趣方面都有一些价值 - 篮球, cricket 和 python,因此这两个配置文件可能比配置文件 1 和配置文件 3 更相似,其中一个配置文件(配置文件 3)没有在配置文件中提及 python。我也不希望只计算距离的相似特征,这肯定会产生错误的结果。
我的第一个问题 - 有什么方法可以通过任何既定的方式来适应这种直觉吗?
我的第二个问题 - 某些个人资料作者可能比其他作者更冗长,如何调整?因为有 4 次 python 出现的详细作者可能与出现 2 次 python.
的不那么冗长的作者相同我没能为这个问题想出好的标题。很抱歉,如果它混淆。
首先,像您已经做的那样计算您的配置文件。然后关键的一步将是某种正常化。您可以将数字除以它们的总数,以便数字总和为 1,或者您可以将它们除以欧几里得范数,以便它们的欧几里得范数为 1。
例如,使用总和归一化,第一个配置文件将变为(四舍五入)
0.57, 0.29, 0.14
并使用欧几里得归一化,它会变成
0.87, 0.44, 0.22
这将确保所有配置文件都在相同的数字范围内表示,并将处理 "overly verbose profile author"。
下面是一个示例 IPython 会话,它显示了如何按行总和对行进行归一化以及如何计算归一化行之间的欧氏距离。您会看到在规范化之后,配置文件 1 和 3 靠得更近了,正如您所期望的那样。
In [22]: p = array([[4,2,1],[2,1,3],[2,1,0]])
In [23]: p
Out[23]:
array([[4, 2, 1],
[2, 1, 3],
[2, 1, 0]])
In [24]: p = p / p.sum(axis=1)[:,newaxis]
In [25]: p
Out[25]:
array([[ 0.57142857, 0.28571429, 0.14285714],
[ 0.33333333, 0.16666667, 0.5 ],
[ 0.66666667, 0.33333333, 0. ]])
In [26]: p.sum(axis=1)
Out[26]: array([ 1., 1., 1.])
In [27]: norm(p[0] - p[1]) # distance 1-2
Out[27]: 0.44543540318737401
In [28]: norm(p[0] - p[2]) # distance 1-3
Out[28]: 0.17817416127494959
In [29]: norm(p[1] - p[2]) # distance 2-3
Out[29]: 0.62360956446232352
最后,如果您想更加重视配置文件是否完全提及兴趣而不是提及频率,您可以在规范化之前执行额外的步骤:只需计算 pow(x, alpha)
对于配置文件向量的每个元素 x
,其中 alpha
是一个介于 0 和 1 之间的参数。这里,1 表示标准线性加权,如前所述,当您使 alpha 接近 0 时,表示仅提及兴趣很重要,而不是频率。例如,使用 alpha = 0.5
(取配置文件的平方根),我们得到:
In [32]: p = array([[4,2,1],[2,1,3],[2,1,0]])
In [33]: p = sqrt(p)
In [34]: p
Out[34]:
array([[ 2. , 1.41421356, 1. ],
[ 1.41421356, 1. , 1.73205081],
[ 1.41421356, 1. , 0. ]])
In [35]: p = p / p.sum(axis=1)[:,newaxis]
In [37]: norm(p[0] - p[1]) # distance 1-2
Out[37]: 0.2353133053319465
In [38]: norm(p[0] - p[2]) # distance 1-3
Out[38]: 0.27881275777438091
In [39]: norm(p[1] - p[2]) # distance 2-3
Out[39]: 0.51412606310632747
现在配置文件 1 和 2 是最接近的匹配项,因为我们更加强调他们都提到了 Python 这一事实,而不是他们提到它的频率。