适用于theano张量的pdist

Sha*_*hai 6 python matlab scipy theano

我有一个theano符号矩阵

x = T.fmatrix('input')
Run Code Online (Sandbox Code Playgroud)

x稍后会被n昏暗的矢量d(火车时间)填充.

我希望theano相当于pdist(scipy.spatial.distance.pdistof pdist),类似于

D = theano.pdist( x )
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

调用scipy.spatial.distance.pdistx直接作为不起作用x在这个阶段只是象征......

更新:我非常希望能够模仿pdist"紧凑"行为:即,仅计算距离矩阵的nx n个条目中的~1/2 .

eic*_*erg 14

pdist来自scipy是一个不同功能的集合 - 没有一个Theano等同于所有这些功能.然而,作为封闭形式的数学表达式的每个特定距离可以在Theano中写下来然后编译.

以minkowski p标准距离为例(复制+可粘贴):

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)
Run Code Online (Sandbox Code Playgroud)

注意abs调用内置函数__abs__,因此abs也是一个theano函数.我们现在可以将其与pdist:

import numpy as np
from scipy.spatial.distance import pdist

rng = np.random.RandomState(42)
d = 20 # dimension
nX = 10
nY = 30
x = rng.randn(nX, d).astype(np.float32)
y = rng.randn(nY, d).astype(np.float32)

ps = [1., 3., 2.]

for p in ps:
    d_theano = f_minkowski(x, x, p)[np.triu_indices(nX, 1)]
    d_scipy = pdist(x, p=p, metric='minkowski')
    print "Testing p=%1.2f, discrepancy %1.3e" % (p, np.sqrt(((d_theano - d_scipy) ** 2).sum()))
Run Code Online (Sandbox Code Playgroud)

这产生了

Testing p=1.00, discrepancy 1.322e-06
Testing p=3.00, discrepancy 4.277e-07
Testing p=2.00, discrepancy 4.789e-07
Run Code Online (Sandbox Code Playgroud)

正如您所看到的那样,对应关系存在,但函数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))
Run Code Online (Sandbox Code Playgroud)

只用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()
Run Code Online (Sandbox Code Playgroud)

生产

Comparing f_minkowski, p=2 and f_euclidean: l2-discrepancy 1.464e-11
Run Code Online (Sandbox Code Playgroud)