<p>看看你的MATLAB代码,你有-</p>
<pre><code>C = bsxfun(@times, permute(A,[4,2,5,1,3]), permute(B, [1,6,2,7,3,4,5])
</code></pre>
<p>所以,本质上-</p>
^{pr2}$
<p>现在,在MATLAB中,我们不得不从更高的维度中借用单例维度,这就是为什么要为<code>6</code>,<code>7</code>为{<cd3>}引入{<cd4>}<code>5</code>为<code>A</code>带来那么多麻烦。在</p>
<p>在NumPy中,我们显式地引入带有<a href="http://docs.scipy.org/doc/numpy-1.10.0/reference/arrays.indexing.html#numpy.newaxis" rel="nofollow">^{<cd7>}/None</a>的元素。因此,对于纽比,我们可以这样说-</p>
<pre><code>B : 1 , N , 2 , N , 3 , 4 , 5
A : N , 2 , N , 1 , 3 , N , N
</code></pre>
<p>,其中<code>N</code>表示新轴。请注意,我们需要在末尾添加新的轴,<code>A</code>以推进其他维度的对齐。相反,这在MATLAB中默认发生。在</p>
<p>使<code>B</code>看起来很容易,因为维度似乎是有序的,我们只需要在适当的位置添加新的轴-<code>B[:,None,:,None,:,:,:]</code>。在</p>
<p>创建这样的<code>A</code>并不是向前看的。忽略<code>A</code>中的<code>N's</code>,我们将得到-<code>A : 2 , 1 , 3</code>。所以,起点应该是置换维度,然后加入被忽略的两个新轴-<code>A.transpose(1,0,2)[None,:,None,:,:,None,None]</code>。在</p>
<p>到目前为止,我们已经-</p>
<pre><code>B (new): B[:,None,:,None,:,:,:]
A (new): A.transpose(1,0,2)[None,:,None,:,:,None,None]
</code></pre>
<p>在NumPy中,我们可以跳过前导的新轴和尾随的非单体dim。所以,我们可以这样简化-</p>
<pre><code>B (new): B[:,None,:,None]
A (new): A.transpose(1,0,2)[:,None,...,None,None]
</code></pre>
<p>最终的结果是这两个扩展版本之间的乘法-</p>
<pre><code>C = A.transpose(1,0,2)[:,None,...,None,None]*B[:,None,:,None]
</code></pre>
<p><strong>运行时测试</strong></p>
<p>我相信@Andras的帖子意味着等效的<code>np.einsum</code>实现类似于:<code>np.einsum('ijk,lmkno->ljmikno',A,B)</code>。在</p>
<pre><code>In [24]: A = np.random.randint(0,9,(10,10,10))
...: B = np.random.randint(0,9,(10,10,10,10,10))
...:
In [25]: C1 = np.einsum('ijk,lmkno->ljmikno',A,B)
In [26]: C2 = A.transpose(1,0,2)[:,None,...,None,None]*B[:,None,:,None]
In [27]: np.allclose(C1,C2)
Out[27]: True
In [28]: %timeit np.einsum('ijk,lmkno->ljmikno',A,B)
10 loops, best of 3: 102 ms per loop
In [29]: %timeit A.transpose(1,0,2)[:,None,...,None,None]*B[:,None,:,None]
10 loops, best of 3: 78.4 ms per loop
In [30]: A = np.random.randint(0,9,(15,15,15))
...: B = np.random.randint(0,9,(15,15,15,15,15))
...:
In [31]: %timeit np.einsum('ijk,lmkno->ljmikno',A,B)
1 loop, best of 3: 1.76 s per loop
In [32]: %timeit A.transpose(1,0,2)[:,None,...,None,None]*B[:,None,:,None]
1 loop, best of 3: 1.36 s per loop
</code></pre>