大步构阵

2024-09-30 00:25:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个数组A1_ijk,并希望将其广播给A2_ijmnk,但仅限于m=n时的情况。否则A2应该用零填充。当然,我可以创建新的空数组并用A1填充它,如下所示:

import numpy as np
A1 = np.random.rand(100, 5, 3)
A2 = np.zeros((100, 5, 2, 2, 3))
A2[..., 0, 0, :] = A1
A2[..., 1, 1, :] = A1

不过,我觉得这可以用更有效的方式来完成。我试过as_strided

^{pr2}$

还有broadcast_to

broadcast_to = np.lib.stride_tricks.broadcast_to
A2=broadcast_to(A1[...,None,None,:], (100,5,2,2,3))

不幸的是,这两种方法都用A1值填充所有m, n对。在

我的问题是,是否可以使用跨步创建我需要的形状数组,而不需要实际复制数据?在


Tags: toimportnumpynonea2a1asnp
3条回答

我可以用np.diag_indices简化编码。我不认为效率是相对于一个快速的解决方案(如果可能的话)。让我们看看我是否可以简化我的开发历史

首先是指数

In [2]: np.diag_indices(2)
Out[2]: (array([0, 1]), array([0, 1]))

更简单的开始;我们不需要2维开始,那些可以改变重塑。我们可能不需要结束维度,但我暂时不谈这个问题:

^{pr2}$

现在构建参考解决方案:

In [4]: A2=np.zeros((4,2,2,3),int)    
In [5]: A2[:,0,0,:]=A1
In [6]: A2[:,1,1,:]=A1

In [7]: A2
Out[7]: 
array([[[[ 0,  1,  2],
         [ 0,  0,  0]],

        [[ 0,  0,  0],    
       [[[ 3,  4,  5],
         [ 0,  0,  0]],

        [[ 0,  0,  0],
         [ 3,  4,  5]]],


       ...

       [[[ 9, 10, 11],
         [ 0,  0,  0]],

         [ 0,  1,  2]]],

          ...
        [[ 0,  0,  0],
         [ 9, 10, 11]]]])

备选方案:

In [8]: A3=np.zeros((4,2,2,3),int)

In [9]: i,j=np.diag_indices(2)

In [10]: A3[:,i,j,:]=A1
...
ValueError: shape mismatch: value array of shape (4,3) could not be broadcast to indexing result of shape (2,4,3)

第一次尝试时形状不匹配

In [12]: A2[:,i,j,:]
Out[12]: 
array([[[ 0,  1,  2],
        [ 0,  1,  2]],

       [[ 3,  4,  5],
        [ 3,  4,  5]],

       [[ 6,  7,  8],
        [ 6,  7,  8]],

       [[ 9, 10, 11],
        [ 9, 10, 11]]])

In [13]: A2[:,i,j,:].shape
Out[13]: (4, 2, 3)

我们需要修改A1,以便它可以广播到目标插槽。在

In [14]: A1.shape
Out[14]: (4, 3)

In [15]: A3[:,i,j,:] = A1[:,None,:]

In [16]: np.allclose(A2,A3)
Out[16]: True

A2[...,i,j,:] = A1[...,None,:]应该处理您的示例。在

更简单的版本,从一维阵列开始,扩展到三维

In [21]: a1=np.arange(3)

In [22]: a3=np.zeros((2,2,3),int)

In [23]: a3[...,i,j,:]=a1[...,None,:]

In [24]: a3[i,j,:]=a1   # equivalent since a1[None,:] is automatic

In [25]: a3
Out[25]: 
array([[[0, 1, 2],
        [0, 0, 0]],

       [[0, 0, 0],
        [0, 1, 2]]])

a3没有a1值的重复模式;或者是这样?在

In [36]: a3.flatten()
Out[36]: array([0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 1, 2])

正如您所发现的,用as_strides填充所有插槽很容易,但仅填充对角线很难:

In [46]: ast(a1,shape=a3.shape, strides=(0,0,4))
Out[46]: 
array([[[0, 1, 2],
        [0, 1, 2]],

       [[0, 1, 2],
        [0, 1, 2]]])

My question is if this is possible to use strides to create the array of the shape i need using strides and without actual copying data?

不是的。作为一种简单的方法,考虑一下如果数组中没有零,则该数组的任何可能视图都不会给出所需的非对角零。在

您需要用至少n阶零填充数据;然后可以设置stride[n]==-stride[m]以达到预期效果,并避免分配n*m个顺序的零。在

但有些事情告诉我,如果你放眼全局,一定会有一个更优雅的解决方案来解决你的问题。在

相关问题 更多 >

    热门问题