我怎样才能用 numpy 优雅地产生这种稀疏模式?

How can I produce this sparsity pattern elegantly with numpy?

对于 D 维问题,我正在尝试生成具有特定稀疏模式的 2d ndarray

我一直在尝试弄清楚如何使用 np.meshgrid 之类的方法交错向量,但就是做不到。

稀疏矩阵(实际上不需要稀疏,只包含 0s 和 1s)的形状为 (2^D, D),其中 D 是维数.

对于 D=2,矩阵如下所示:

two_d = [
    [0, 0],
    [1, 0],
    [0, 1],
    [1, 1],
]

对于 D=3 是这样的:

three_d = [
    [0, 0, 0],
    [1, 0, 0],
    [0, 1, 0],
    [1, 1, 0],
    [0, 0, 1],
    [1, 0, 1],
    [0, 1, 1],
    [1, 1, 1],
]

这是一个非常明显的稀疏模式,但我正在努力弄清楚如何用 numpy 优雅地重现它。

注意:行顺序实际上并不重要,只要所有行都存在即可。

仁者见仁,智者见智。有许多工具可以生成这些值;将它们放入所需的布局只是基本的 numpy 操作。

生成这些数组的一个很好的基本方法是:

In [6]: np.array(list(itertools.product([0,1],repeat=2)))
Out[6]: 
array([[0, 0],
       [0, 1],
       [1, 0],
       [1, 1]])
In [7]: np.array(list(itertools.product([0,1],repeat=3)))
Out[7]: 
array([[0, 0, 0],
       [0, 0, 1],
       [0, 1, 0],
       [0, 1, 1],
       [1, 0, 0],
       [1, 0, 1],
       [1, 1, 0],
       [1, 1, 1]])

来自评论:

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

       [[0, 1],
        [0, 1]]])
In [17]: np.indices((2,)*2).T.reshape(-1,2)
Out[17]: 
array([[0, 0],
       [1, 0],
       [0, 1],
       [1, 1]])
In [18]: np.indices((2,)*3).T.reshape(-1,3)
Out[18]: 
array([[0, 0, 0],
       [1, 0, 0],
       ...

In [20]: np.meshgrid(np.arange(2),np.arange(2),indexing='ij')
Out[20]: 
[array([[0, 0],
        [1, 1]]),
 array([[0, 1],
        [0, 1]])]
In [21]: np.transpose(np.meshgrid(np.arange(2),np.arange(2),indexing='ij')).resh
    ...: ape(-1,2)
Out[21]: 
array([[0, 0],
       [1, 0],
       [0, 1],
       [1, 1]])

'ij' 不是必需的;它只是生成一组初始数组,看起来像 indices.

mgrid也可以用。和:

np.array(list(np.ndindex(2,2,2)))

另一种方法是逆向工程three_d

In [55]: res = np.zeros((2**3,3),int)

设置第一列的所有其他元素很简单:

In [56]: res[1::2,0]=1
In [57]: res
Out[57]: 
array([[0, 0, 0],
       [1, 0, 0],
       [0, 0, 0],
       [1, 0, 0],
       [0, 0, 0],
       [1, 0, 0],
       [0, 0, 0],
       [1, 0, 0]])

在第二个中设置值对比较棘手:

In [58]: res[:,1].reshape(-1,4)[:,2:]=1
In [59]: res
Out[59]: 
array([[0, 0, 0],
       [1, 0, 0],
       [0, 1, 0],
       [1, 1, 0],
       [0, 0, 0],
       [1, 0, 0],
       [0, 1, 0],
       [1, 1, 0]])

设置第三个连续块同样简单:

In [60]: res[4:,2]=1
In [61]: res
Out[61]: 
array([[0, 0, 0],
       [1, 0, 0],
       [0, 1, 0],
       [1, 1, 0],
       [0, 0, 1],
       [1, 0, 1],
       [0, 1, 1],
       [1, 1, 1]])