numpy ndarrays 中匹配行之间的余弦相似度
Cosine similarity between matching rows in numpy ndarrays
我有 2 个 (n_samples, n_dimensions)
的 ndarrays,我想要每一对对应的行,所以输出将是 (n_samples, )
使用 sklearn's implementation
我得到 (n_samples, n_samples)
结果 - 这显然进行了很多不相关的计算,这在我的情况下是不可接受的。
使用 1 - scipy's implementation
是不可能的,因为它需要向量而不是矩阵。
执行我正在寻找的内容的最有效方法是什么?
假设两个数组x
和y
具有相同的形状,
- 使用
np.einsum
(reference) 计算 element-wise 点积
- 为
x
和 y
的每一行计算 L2(欧几里德)范数的乘积
- 将 (1) 的结果除以 (2)
def matrix_cosine(x, y):
return np.einsum('ij,ij->i', x, y) / (
np.linalg.norm(x, axis=1) * np.linalg.norm(y, axis=1)
)
还有一些测试代码;
x = np.random.randn(100000, 100)
%timeit matrix_cosine(x, x)
82.8 ms ± 2.94 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
assert np.allclose(matrix_cosine(x, x), np.ones(x.shape[0]))
我有 2 个 (n_samples, n_dimensions)
的 ndarrays,我想要每一对对应的行,所以输出将是 (n_samples, )
使用 sklearn's implementation
我得到 (n_samples, n_samples)
结果 - 这显然进行了很多不相关的计算,这在我的情况下是不可接受的。
使用 1 - scipy's implementation
是不可能的,因为它需要向量而不是矩阵。
执行我正在寻找的内容的最有效方法是什么?
假设两个数组x
和y
具有相同的形状,
- 使用
np.einsum
(reference) 计算 element-wise 点积
- 为
x
和y
的每一行计算 L2(欧几里德)范数的乘积
- 将 (1) 的结果除以 (2)
def matrix_cosine(x, y):
return np.einsum('ij,ij->i', x, y) / (
np.linalg.norm(x, axis=1) * np.linalg.norm(y, axis=1)
)
还有一些测试代码;
x = np.random.randn(100000, 100)
%timeit matrix_cosine(x, x)
82.8 ms ± 2.94 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
assert np.allclose(matrix_cosine(x, x), np.ones(x.shape[0]))