首页 > 解决方案 > 如何使用 Numpy/Scipy 找到与一个数组最相似的数值数组?

问题描述

假设我有一个包含 5 个单词的列表:

[this, is, a, short, list]

此外,我可以通过计算上面列表中单词的出现次数并将这些计数表示为向量来对某些文本进行分类:

N = [1,0,2,5,10] # 1x this, 0x is, 2x a, 5x short, 10x list found in the given text

以同样的方式,我对许多其他文本进行分类(计算每个文本的 5 个单词,并将它们表示为计数 - 每行代表一个不同的文本,我们将与 N 进行比较):

M = [[1,0,2,0,5],
     [0,0,0,0,0],
     [2,0,0,0,20],
     [4,0,8,20,40],
     ...]

现在,我想从 M 中找到与 N 最相似的前 1(2、3 等)行。或者在简单的单词上,与我的初始文本最相似的文本。

挑战在于,仅检查 N 和每行与 M 之间的距离是不够的,因为例如行 M4 [4,0,8,20,40] 与 N 的距离非常不同,但仍然成比例(通过一个因子4),因此非常相似。例如,M4 行中的文本可以是 N 表示的文本的 4 倍,所以自然所有计数都将是 4 倍。

解决这个问题的最佳方法是什么(从 M 到 N 中的文本找到最多的 1、2、3 等相似文本)?

标签: numpyvectorscipy

解决方案


一般来说,用于相似度的词袋(即你的数组)最广泛的标准技术是检查余弦相似度度量。这会将你的包n(这里是 5 个)单词映射到一个n维空间,每个数组都是该空间中的一个点(本质上也是一个点向量)。最相似的向量(/点)将是与N该空间中的文本角度最小的向量(这会自动处理成比例的向量,因为它们的角度会很接近)。因此,这是它的代码(假设M并且N是问题中引入的类似形状的numpy数组):

import numpy as np
cos_sim = M[np.argmax(np.dot(N, M.T)/(np.linalg.norm(M)*np.linalg.norm(N)))]

[ 4 0 8 20 40]为您的输入提供输出。


推荐阅读