numpy中检查向量是否对齐或方向相反(截断的SVD后处理)的最快方法

问题描述 投票:0回答:1

我有一堆矢量,它们存储在矩阵U的列中。我也有一个包含列向量的矩阵V。 V中的每个向量都可以是

  • 与U中的对等几乎相同,带有数字近似值
  • 或具有相反的符号,带有数字近似值。

目标是找到一个数组,如果向量的方向相同,则其值为1;如果向量方向相反,则为-1。

另外两件事:

  • 我只对第一个符号感兴趣,而不是全部(在下面的示例中,10000个中的100个)。
  • V以其转置形式(Vt)给出

到目前为止,我已经找到了三种解决此问题的方法:

from timeit import timeit
import numpy as np

# create fake SVD output
n_components = 100
n_samples = 10000
U = np.random.random((n_samples, n_samples - 1))
true_signs = np.sign(np.random.random(n_samples - 1) - 0.5)
Vt = np.multiply(U, true_signs[None, :]).T
# simulate some numerical imprecision
Vt += np.random.random((n_samples - 1, n_samples)) * 0.001

# 3 competing methods
def compute_signs_dot():
    VtU = np.dot(Vt[:n_components, :], U[:, :n_components])
    signs = np.sign(np.diag(VtU))
    np.testing.assert_equal(signs, true_signs[:n_components])

def compute_signs_mul():
    diag_VtU = np.multiply(Vt[:n_components, :].T,
                          U[:, :n_components]).sum(axis=0)
    signs = np.sign(diag_VtU)
    np.testing.assert_equal(signs, true_signs[:n_components])

def compute_signs_sign():
    signs = np.multiply(np.sign(Vt[:n_components, :].T),
                        np.sign(U[:, :n_components])).sum(axis=0)
    signs = np.sign(signs)
    np.testing.assert_equal(signs, true_signs[:n_components])

# compare execution times
print("compute_signs_dot: %.3fs" % timeit(compute_signs_dot, number=100))
print("compute_signs_mul: %.3fs" % timeit(compute_signs_mul, number=100))
print("compute_signs_sign: %.3fs" % timeit(compute_signs_sign, number=100))

产量

compute_signs_dot: 2.001s
compute_signs_mul: 0.786s
compute_signs_sign: 1.693s

因此,到目前为止看来,最快的方法是通过将term与term和sum(compute_signs_mul)相乘来计算每个列索引处的矢量对之间的标量积。

可以以更快的速度或类似的速度欣赏任何其他方法。

注意:正如一些读者会注意到的,这是对截断的SVD输出的后处理,以便通过查找其符号将奇异值转换为特征值。

python numpy vector svd eigenvalue
1个回答
0
投票

我们可以使用np.einsum-

np.einsum
© www.soinside.com 2019 - 2024. All rights reserved.