Python 在numpy中执行交叉差异

Python 在numpy中执行交叉差异,python,numpy,Python,Numpy,我想执行如下“交叉差异”: def crossdiff(a,b): c = [] for a1 in range(len(a)): for b1 in range(len(b)): c.append (a[a1]-b[b1]) x = numpy.array(c) x.reshape(len(a),len(b)) return x 交叉差异([a,b],[c,d])=[a-c,a-d],[b-c,b-d]] 我有一

我想执行如下“交叉差异”:

def crossdiff(a,b):
    c = []
    for a1 in range(len(a)):
        for b1 in range(len(b)):
            c.append (a[a1]-b[b1])
    x = numpy.array(c)
    x.reshape(len(a),len(b))
    return x
交叉差异([a,b],[c,d])=[a-c,a-d],[b-c,b-d]]

我有一个在python中执行此操作的例程,如下所示:

def crossdiff(a,b):
    c = []
    for a1 in range(len(a)):
        for b1 in range(len(b)):
            c.append (a[a1]-b[b1])
    x = numpy.array(c)
    x.reshape(len(a),len(b))
    return x
问题是我必须创建一个python数组并将结果填充到其中,然后再转换回numpy数组。我希望能够得到numpy向量a和b,得到一个包含所有差异的numpy数组c,因为上面的代码对于较大的向量大小来说性能很差

是否有必要将上述计算作为“纯”numpy操作执行

编辑测试结果:

我通过Python分析器运行了本线程中列出的所有四个实现,以进行比较。我必须在工作站上运行它们,因为最初的实现使用了~4GB内存和10k元素

import numpy
import cProfile

def cross_diff(A, B):
    return A[:,None] - B[None,:]

def crossdiff2 (a,b):
    ap = numpy.tile (a, (numpy.shape(b)[0],1))
    bp = numpy.tile (b, (numpy.shape(a)[0],1))

    return ap - bp.transpose()

def crossdiff(a,b):
    c = []
    for a1 in range(len(a)):
        for b1 in range(len(b)):
            c.append (a[a1]-b[b1])
    x = numpy.array(c)
    x.reshape(len(a),len(b))
    return x

a = numpy.array(range(10000))
b = numpy.array(range(10000))

cProfile.run('crossdiff (a,b)')
cProfile.run('crossdiff2 (a,b)')
cProfile.run('cross_diff (a,b)')
cProfile.run('numpy.subtract.outer (a,b)')
结果: 最初的python是74.147秒,我的版本是1.656秒,第三个实现是0.296,第四个实现是0.288。

试试:

import numpy as np

np.array([a,b])[:,None] - np.array([c,d,e])[None,:]
一点解释:索引中的
None
可以根据需要扩展维度。因此,实际计算将是:

a a a     c d e     a-c  a-d  a-e
       -         =  
b b b     c d e     b-c  b-d  b-e
非常有用的是,索引中的
None

还有一个例子:

import numpy as np

def cross_diff(A, B):
    return A[:,None] - B[None,:]

vec_a = np.array([1,2,3,4])
vec_b = np.array([3,2,1])

print cross_diff(vec_a, vec_b)

基于@DrV概述的技术,我提出了以下建议:

def crossdiff2 (a,b):
    ap = numpy.tile (a, (numpy.shape(b)[0],1))
    bp = numpy.tile (b, (numpy.shape(a)[0],1))

    print ap.transpose()

    return ap - bp.transpose()

它给出了与上面相同的答案,但将所有数据操作保留在numpy中。

通过使用ufuncs的
.outer
方法,您可以获得相同的结果,而无需为广播添加显式维度。例如:

>>> np.subtract.outer([1, 2], [3, 4, 5])
array([[-2, -3, -4],
       [-1, -2, -3]])

它还有一个额外的好处,即接受任何iterable作为输入,您不需要首先将它们转换为数组。

索引中的None是numpy数组的特殊功能还是可以使用任何数组完成的功能?@BelowtheRadar:这是一个numpy技巧。基本python数组不支持多维索引或任何元素计算。我看到了按形状(b)复制a和按形状(a)复制b的概念,但当我尝试此操作时,它返回一个由1个元素值组成的数组,而不是n个元素值。@Guy,你试过我的示例吗?用一些数字代替
a
b
c
d
e
。如果您有1d数组
A
B
,请尝试
A[:,无]-B[无,:]
。我在我的答案末尾添加了一个进一步的例子。我确实尝试过了,我得到了这个:
code
>>np.array([1,2,3])[:,None]-np.array([1,2,3])[:,None]array([0],[0])
code
很好的尝试!但不要试图过度优化。与普通解决方案相比,这要慢得多(大约x 8):)