pdist 对于theano tens

2024-10-01 04:43:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个符号矩阵

x = T.fmatrix('input')

x稍后将由n的dim d向量填充(在火车时刻)。在

我想要一个pdist^{}^{})的等价物,类似于

^{pr2}$

我怎样才能做到这一点?在

直接调用x上的scipy.spatial.distance.pdist在这个阶段并不像{}那样起作用,只是象征性的。。。在

更新:我非常希望能够模拟pdist“紧凑”行为:即只计算距离矩阵的nxn条目的~1/2。在


Tags: 距离input符号矩阵scipy阶段向量spatial
2条回答

scipy中的pdist是不同函数的集合-不存在一个对所有这些函数同时进行等效的方法。然而,每一个特定的距离,作为一个封闭的数学表达式,可以写在表中,然后进行编译。在

以minkowskip范数距离(copy+pasteable)为例:

import theano
import theano.tensor as T
X = T.fmatrix('X')
Y = T.fmatrix('Y')
P = T.scalar('P')
translation_vectors = X.reshape((X.shape[0], 1, -1)) - Y.reshape((1, Y.shape[0], -1))
minkowski_distances = (abs(translation_vectors) ** P).sum(2) ** (1. / P)
f_minkowski = theano.function([X, Y, P], minkowski_distances)

注意,abs调用内置的__abs__,因此abs也是一个函数。我们现在可以将其与pdist进行比较:

^{pr2}$

这就产生了

Testing p=1.00, discrepancy 1.322e-06
Testing p=3.00, discrepancy 4.277e-07
Testing p=2.00, discrepancy 4.789e-07

正如您所看到的,对应关系是存在的,但是函数f_minkowski稍微更通用,因为它比较两个可能不同数组的行。如果将同一数组作为输入传递两次,f_minkowski返回一个矩阵,而pdist返回一个没有冗余的列表。如果需要这种行为,也可以完全动态地实现,但我将坚持这里的一般情况。在

但是,应该注意一种特殊化的可能性:在p=2的情况下,通过二项式公式计算变得更简单,这可以用来节省内存中宝贵的空间:而上面实现的一般Minkowski距离创建了一个3D数组(由于避免了for循环和累积求和),它是禁止的,取决于d(和nX, nY),对于p=2我们可以写

squared_euclidean_distances = (X ** 2).sum(1).reshape((X.shape[0], 1)) + (Y ** 2).sum(1).reshape((1, Y.shape[0])) - 2 * X.dot(Y.T)
f_euclidean = theano.function([X, Y], T.sqrt(squared_euclidean_distances))

它只使用O(nX * nY)空间而不是O(nX * nY * d)我们检查对应关系,这次是针对一般问题:

d_eucl = f_euclidean(x, y)
d_minkowski2 = f_minkowski(x, y, 2.)
print "Comparing f_minkowski, p=2 and f_euclidean: l2-discrepancy %1.3e" % ((d_eucl - d_minkowski2) ** 2).sum()

屈服

Comparing f_minkowski, p=2 and f_euclidean: l2-discrepancy 1.464e-11

我以前没有使用过Theano,但是这里有一个基于纯Numpy函数的解决方案(也许您可以将它转换为等效的Theano函数)。请注意,我在下面的表达式中使用了automaticbroadcasting,因此如果Theano不支持它,您可能需要显式重写它):

# X is an m-by-n matrix (rows are examples, columns are dimensions)
# D is an m-by-m symmetric matrix of pairwise Euclidean distances
a = np.sum(X**2, axis=1)
D = np.sqrt((a + a[np.newaxis].T) - 2*np.dot(X, X.T))

它基于这样一个事实:||u-v||^2 = ||u||^2 + ||v||^2 - 2*u.v。(我用MATLAB在我的previousanswers中展示了这一点)

以下是与Scipy现有函数的比较:

^{pr2}$

差异应该可以忽略不计,接近机器epsilon(np.spacing(1)):

>>> np.linalg.norm(D1-D2)
8.5368137554718277e-16

高温


编辑:

下面是另一个单循环实现:

def my_pdist_compact(X):
    D = np.empty(shape=[0,0], dtype=X.dtype)
    for i in range(X.shape[0]-1):
        D = np.append(D, np.sqrt(np.sum((X[i,] - X[i+1:,])**2, axis=1)))
    return D

相当于MATLAB代码:

function D = my_pdist_compact(X)
    n = size(X,1);
    D = cell(n-1,1);
    for i=1:n-1
        D{i} = sqrt(sum(bsxfun(@minus, X(i,:), X(i+1:end,:)).^2, 2));
    end
    D = vertcat(D{:});
end

这将返回紧凑形式的成对距离(对称矩阵的上三角部分)。这与pdist的输出相同。使用squareform将其转换为完整矩阵。在

>>> d1 = my_pdist_compact(X)
>>> d2 = pdist(X)    # from scipy.spatial.distance
>>> (d1 == d2).all()
True

我将把它留给您看看是否可以使用ano编写等价的loop(参见^{})!在

相关问题 更多 >