我有两个2乘2复数矩阵的数组,我想知道最快的乘法方法是什么。 (我想对矩阵数组的元素进行矩阵乘法。)目前,我有
numpy.array(map(lambda i: numpy.dot(m1[i], m2[i]), range(l)))
但是,一个人能比这更好吗?
谢谢,
v923z
答案 0 :(得分:1)
我认为你要找的答案是here。不幸的是,这是一个涉及重塑的相当混乱的解决方案。
答案 1 :(得分:1)
numpy.einsum是这个问题的最佳解决方案,它提到了DaveP参考的底部。代码干净,易于理解,比循环遍历数组并逐个进行乘法快一个数量级。以下是一些示例代码:
import numpy
l = 100
m1 = rand(l,2,2)
m2 = rand(l,2,2)
m3 = numpy.array(map(lambda i: numpy.dot(m1[i], m2[i]), range(l)))
m3e = numpy.einsum('lij,ljk->lik', m1, m2)
%timeit numpy.array(map(lambda i: numpy.dot(m1[i], m2[i]), range(l)))
%timeit numpy.einsum('lij,ljk->lik', m1, m2)
print np.all(m3==m3e)
以下是在ipython笔记本中运行时的返回值:
1000次循环,最佳3:每循环479μs
10000次循环,最佳3次:每循环48.9μs
真的的
答案 2 :(得分:0)
如果m1
和m2
是2x2复数矩阵的1维数组,则它们基本上具有形状(l,2,2)
。因此,最后两个轴上的矩阵乘法相当于将m1
的最后一个轴与m2
的倒数第二个轴的乘积相加。这正是np.dot所做的:
np.dot(m1,m2)
或者,既然你有复杂的矩阵,也许你想首先采用m1
的复共轭。在这种情况下,请使用np.vdot
。
PS。如果m1
是2x2复杂矩阵的列表,那么可能会看看您是否可以从一开始就重新排列代码以使m1
成为一个形状(l,2,2)
的数组。
如果那是不可能的,列表理解
[np.dot(m1[i],m2[i]) for i in range(l)]
比使用map
使用lambda
更快,但执行l
np.dot
比在两个数组上执行一个np.dot
要慢如上所述,形成(l,2,2)
。
答案 3 :(得分:0)
如果m1和m2是2x2复数矩阵的1维阵列,那么它们基本上具有形状(1,2,2)。因此,最后两个轴上的矩阵乘法相当于将m1的最后一个轴与m2的倒数第二个轴的乘积相加。这正是np.dot所做的:
但这不是np.dot的作用。
a = numpy.array([numpy.diag([1, 2]), numpy.diag([2, 3]), numpy.diag([3, 4])])
生成一个2乘2矩阵的(3,2,2)数组。但是,numpy.dot(a,a)创建了6个矩阵,结果的形状为(3,2,3,2)。这不是我需要的。我需要的是一个包含numpy.dot(a [0],a [0]),numpy.dot(a [1],a [1]),numpy.dot(a [2],a [2] )...
[np.dot(m1[i],m2[i]) for i in range(l)]
应该可以工作,但我还没有检查过,lambda表达式的映射是否更快。
干杯,
v923z
编辑:for循环和地图以大约相同的速度运行。这是numpy.array的转换消耗了大量的时间,但是这两种方法都必须这样做,所以这里没有任何好处。
答案 4 :(得分:0)
可能是问题太老了,但我还在寻找答案。
我试过这段代码
a=np.asarray(range(1048576),dtype='complex');b=np.reshape(a//1024,(1024,1024));b=b+1J*b
%timeit c=np.dot(b,b)
%timeit d=np.einsum('ij, ki -> jk', b,b).T
结果是:'dot'
10 loops, best of 3: 174 ms per loop
代表'einsum'
1 loops, best of 3: 4.51 s per loop
我已经检查过c和d是否相同
(c==d).all()
True
仍然'点'是赢家,我仍在寻找更好的方法,但没有成功