<p>scipy中的<code>pdist</code>是不同函数的集合-不存在一个对所有这些函数同时进行等效的方法。然而,每一个特定的距离,作为一个封闭的数学表达式,可以写在表中,然后进行编译。在</p>
<p>以minkowski<code>p</code>范数距离(copy+pasteable)为例:</p>
<pre><code>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)
</code></pre>
<p>注意,<code>abs</code>调用内置的<code>__abs__</code>,因此<code>abs</code>也是一个函数。我们现在可以将其与<code>pdist</code>进行比较:</p>
^{pr2}$
<p>这就产生了</p>
<pre><code>Testing p=1.00, discrepancy 1.322e-06
Testing p=3.00, discrepancy 4.277e-07
Testing p=2.00, discrepancy 4.789e-07
</code></pre>
<p>正如您所看到的,对应关系是存在的,但是函数<code>f_minkowski</code>稍微更通用,因为它比较两个可能不同数组的行。如果将同一数组作为输入传递两次,<code>f_minkowski</code>返回一个矩阵,而<code>pdist</code>返回一个没有冗余的列表。如果需要这种行为,也可以完全动态地实现,但我将坚持这里的一般情况。在</p>
<p>但是,应该注意一种特殊化的可能性:在<code>p=2</code>的情况下,通过二项式公式计算变得更简单,这可以用来节省内存中宝贵的空间:而上面实现的一般Minkowski距离创建了一个3D数组(由于避免了for循环和累积求和),它是禁止的,取决于<code>d</code>(和<code>nX, nY</code>),对于<code>p=2</code>我们可以写</p>
<pre><code>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))
</code></pre>
<p>它只使用<code>O(nX * nY)</code>空间而不是<code>O(nX * nY * d)</code>我们检查对应关系,这次是针对一般问题:</p>
<pre><code>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()
</code></pre>
<p>屈服</p>
<pre><code>Comparing f_minkowski, p=2 and f_euclidean: l2-discrepancy 1.464e-11
</code></pre>