背景:
我正在实现顺序反向选择算法,以从数据集中选择特征。所讨论的数据集是MNIST。我有60000个长度为784的向量。
该算法要求我从784中删除一个特性,即fi
,并选择其余的783个特性,在下面的代码中称为selection
。然后,我必须计算每个向量的Mahalanobis到它的尊重类的平均值。一旦这个迭代完成,我就省略了两个特性,然后是三个特性等等。每一次迭代都需要3分钟。
我必须选择500个特征,所以上面是重复500次,所以在总的Mahalanobis距离是计算500 x 784 = 392,000
倍。这要求我计算协方差矩阵的逆。这个协方差矩阵的逆不存在,因为它是奇异的,所以我使用的是numpy的伪逆。
问题
就像你可以想象到的,上面的速度非常慢。计算伪逆是一个最慢的过程.我想我可以先计算伪逆,然后删除与fi
相关的相应列和行。然而,结果表明,这个伪逆矩阵并不等于从我已经删除fi
的向量中直接计算的伪逆矩阵。
我试过什么
我在很大程度上尝试过将其矢量化,并对数组的堆栈进行处理,结果发现分解方法更慢。我试过np.einsum,cdist,甚至numexpr。什么都帮不上忙。
这让我相信,我加速这个过程的最佳机会就是将协方差和伪逆计算从这个循环中移出。这是我目前的代码:
def mahalanobis(self, data, lbls, selection):
subset data[:,tuple(selection)]
for n in range(10):
class_rows = subset[np.where(y == n)]
mean = np.mean(class_rows, axis = )
pseudoInverse = pinv(covariance(class_rows))
delta = C - u
d[n] = np.mean(np.sum(((delta @ pseudoInverse) * delta), axis = -1))
return np.mean(d)
问题
我怎样才能加快计算速度?从我在过去一周所做的测试来看,这一计算中最慢的部分似乎是行pseudoInverse = pinv(covariance(class_rows))
。
发布于 2019-03-10 20:12:18
现在,您的代码实质上是:
def mahalanobis(delta, cov):
ci = np.linalg.pinv(cov)
return np.sum(((delta @ ci) * delta), axis=-1)
你可以通过以下方法来加速这件事:
svd
而不是pinv
,并消除不使用的共轭。eigh
代替svd
,利用协方差矩阵的对称性def mahalanobis_eigh(delta, cov):
s, u = np.linalg.eigh(cov)
# note: missing filtering of small s, which you might want to consider adding - pinv already does this for you
ci = u @ (1/s[...,None] * u.T)
return np.sum(((delta @ ci) * delta), axis=-1)
值得注意的是,这个函数和您的函数对于复杂的值都没有正确的工作。
https://stackoverflow.com/questions/55094599
复制相似问题