计算3D和2D NumPy阵列的加权和

时间:2017-12-09 21:44:59

标签: python numpy

假设我有一个形状为(n,3)的2D NumPy阵列A和一个形状为(x,y,n)的3D阵列B.我想创建一个形状为(x,y,3)的3D阵列Y - 这是一个RGB图像。

B的第三维包含概率[0,1],其总和为1.数组A是RGB颜色的列表(每种概率一种颜色)。 对于B的第3维中的每个元素C,我想计算A * C的总和,以便得到RGB颜色向量。

示例

将色彩图A指定为

A = [(255   0   0),
     (  0 255   0),
     (  0   0 255)]

和点(x,y)处的B的第三维中的元素C为

C = [0.2, 0.6, 0.20]

我想将C' = sum(A * C)计算为

  (255   0   0) * 0.2
+ (  0 255   0) * 0.6
+ (  0   0 255) * 0.2
---------------------
  ( 51 153  51)

并指定

Y[x, y, :] = C'

我知道我可以用for循环遍历x和y并一次计算每个元素但是我想知道这是否可以以矢量化的方式完成,我不必自己迭代数组(主要是出于性能原因)。

2 个答案:

答案 0 :(得分:2)

方法numpy.einsum方便:

np.einsum('ij,kli->klj', A, B)

符号表示:将A[i, j]乘以B[k, l, i]并加i;将结果放在单元格[k, l, j]中。

示例:

A = np.array([(255, 0, 0), (0, 255, 0), (0, 0, 255)])
B = np.array([[[0.2, 0.6, 0.20], [0.2, 0.2, 0.60]], [[0.4, 0.4, 0.2], [0.3, 0.3, 0.4]]])
Y = np.einsum('ij,kli->klj', A, B)

然后Y

array([[[  51. ,  153. ,   51. ],
        [  51. ,   51. ,  153. ]],

       [[ 102. ,  102. ,   51. ],
        [  76.5,   76.5,  102. ]]])

答案 1 :(得分:2)

sum-reducing的第一个轴AB的第三个轴相距C = np.tensordot(B,A,axes=((2),(0))) ,其余的轴展开。这是一个完美的设置,可以将基于BLAS的矩阵乘法用于张量 - np.tensordot,就像这样 -

2D

Related post to understand tensordot

我们也可以手动重塑为2D并使用np.dotB.reshape(-1,n).dot(A).reshape(x,y,3) 的矩阵乘法,就像这样 -

B.dot(A)

请注意,B也可以正常工作,但这样会更慢,很可能是因为它会遍历2D的第一个轴,同时为每个2D执行A矩阵乘法将其与In [180]: np.random.seed(0) ...: x,y,n = 100,100,100 ...: A = np.random.rand(n,3) ...: B = np.random.rand(x,y,n) # @Crazy Ivan's soln In [181]: %timeit np.einsum('ij,kli->klj', A, B) 100 loops, best of 3: 4.21 ms per loop In [182]: %timeit np.tensordot(B,A,axes=((2),(0))) 1000 loops, best of 3: 1.72 ms per loop In [183]: np.random.seed(0) ...: x,y,n = 200,200,200 ...: A = np.random.rand(n,3) ...: B = np.random.rand(x,y,n) # @Crazy Ivan's soln In [184]: %timeit np.einsum('ij,kli->klj', A, B) 10 loops, best of 3: 33.2 ms per loop In [185]: %timeit np.tensordot(B,A,axes=((2),(0))) 100 loops, best of 3: 15.3 ms per loop 隔开。

运行时测试 -

<div class="form-group">
      <label>Branch</label>
      <select name="branch"  id="branch_" onChange="getState(this.value)" class="form-control" required>
        <option>Choose your Branch</option> 
        <?php foreach ($branchessss as $key) { ?>
        <option value="<?php echo $key['branch_id']; ?>"><?php echo $key['branch_name']; ?></option>
        <?php } ?>
      </select>
    </div>
  </div>
  <div class="col-xs-6">
    <br>
    <div class="form-group">
      <label>Stylist</label>
      <div class="controls" id="statediv">
        <select class="form-control" id="stylistname_" name="stylistname" required>
          <option>--</option>
        </select>
      </div>
    </div>
  </div>