我使用的算法要求每个示例都有一个矩阵,比如Xi
ai x b
,并且对于每个O(n^2)
对示例,我发现差异在每一行Xiu - Xjv
之间,然后对外部产品sum_u sum_v np.outer(Xiu - Xjv, Xiu - Xjv)
求和。
不幸的是,这个内部双重总和相当慢,并且导致运行时间在大型数据集上失控。现在我只是使用for循环来做到这一点。是否有一些pythonic方法来加速这种内部操作?我一直在努力思考,没有运气。
为了澄清,对于每个n
示例,都有一个矩阵Xi
,其维度为ai x b
,其中ai
对于每个示例都不同。对于每对(Xi, Xj)
,我想浏览两个矩阵之间的所有O(ai * bi)
对行,并找到Xiu - Xjv
,将其外部产品与np.outer(Xiu - Xjv, Xiu - Xjv)
一起取出,并且最后总结所有这些外部产品。
例如:假设D是[[1,2],[3,4]]
,我们只是为两个矩阵使用它。
然后,即一步可能是np.outer(D[0] - D[1], D[0] - D[1])
,它将是矩阵[4,4],[4,4]
。
简单地说,(0,0)和(1,1)只是0矩阵,而(0,1)和(1,0)都是4个矩阵,所以对的所有四个外积的最终总和将是[[8,8],[8,8]]
。
答案 0 :(得分:2)
numpy.tensordot
进行一次巧妙的调用即可完成,但无论如何这似乎已经消除了所有Python级别的循环:
import numpy
def slow( a, b=None ):
if b is None: b = a
a = numpy.asmatrix( a )
b = numpy.asmatrix( b )
out = 0.0
for ai in a:
for bj in b:
dij = bj - ai
out += numpy.outer( dij, dij )
return out
def opsum( a, b=None ):
if b is None: b = a
a = numpy.asmatrix( a )
b = numpy.asmatrix( b )
RA, CA = a.shape
RB, CB = b.shape
if CA != CB: raise ValueError( "input matrices should have the same number of columns" )
out = -numpy.outer( a.sum( axis=0 ), b.sum( axis=0 ) );
out += out.T
out += RB * ( a.T * a )
out += RA * ( b.T * b )
return out
def test( a, b=None ):
print( "ground truth:" )
print( slow( a, b ) )
print( "optimized:" )
print( opsum( a, b ) )
print( "max abs discrepancy:" )
print( numpy.abs( opsum( a, b ) - slow( a, b ) ).max() )
print( "" )
# OP example
test( [[1,2], [3,4]] )
# non-symmetric example
a = [ [ 1, 2, 3 ], [-4, 5, 6 ], [7, -8, 9 ], [ 10, 11, -12 ] ]
a = numpy.matrix( a, dtype=float )
b = a[ ::2, ::-1 ] + 15
test( a, b )
# non-integer example
test( numpy.random.randn( *a.shape ), numpy.random.randn( *b.shape ) )
使用该(相当任意的)示例输入,opsum
的时间(在IPython中使用timeit opsum(a,b)
测量)仅比slow
好3-5倍。但是当然它会更好地扩展很多:将数据点的数量扩大100倍,将要素的数量扩大10倍,然后我们就已经开始研究因子 - 10,000速度增加。