如何解读numpy高级索引解决方案
How to interpret numpy advanced indexing solution
我有一段 我知道有效的 numpy 代码。我知道这一点,因为我已经在我的通用案例中成功地对其进行了测试。但是,在反复参考文档和反复试验两个小时后,我得出了解决方案。我不明白我怎么知道 凭直觉。
设置:
a = np.zeros((5,5,3))
目标:设置为 1 轴 1 的索引 0,1、轴 2 的 0,1、轴 3 的所有索引和轴 1 的索引 3,4、轴 2 的索引 3,4、轴 3 的所有
更清晰的目标:将块1和2的前两行设置为1,将块3和4的后两行设置为1
结果:
ax1 =np.array([np.array([0,1]),np.array([3,4])])
ax1 =np.array([x[:,np.newaxis] for x in ax1])
ax2 = np.array([[[0,1]],[[3,4]]])
a[ax1,ax2,:] = 1
a
输出:
array([[[1., 1., 1.],
[1., 1., 1.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[1., 1., 1.],
[1., 1., 1.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[1., 1., 1.],
[1., 1., 1.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[1., 1., 1.],
[1., 1., 1.]]])
我倾向于相信我应该能够查看相关矩阵的形状、索引的形状和索引操作以直观地了解输出。但是,我无法将这个故事放在一起。比如,它正在改变的子空间的最终形状是什么? 您如何解释它的工作原理?
形状:
input: (5, 5, 3)
ind1: (2, 2, 1)
ind2: (2, 1, 2)
final_op: input[ind1, ind2, :]
有形状
ind1: (2, 2, 1)
ind2: (2, 1, 2)
他们 broadcast
一起 select a (2,2,2) space
In [4]: ax1
Out[4]:
array([[[0],
[1]],
[[3],
[4]]])
In [5]: ax2
Out[5]:
array([[[0, 1]],
[[3, 4]]])
因此对于第一个维度(块),它是 selecting 块 0、1、3 和 4。在第二个维度中,它也是 selecting 这些行。
前 2 个块的前 2 行和后 2 个块的后 2 行加在一起。这就是结果中出现 1 的位置。
创建索引数组的更简单方法:
In [7]: np.array([[0,1],[3,4]])[:,:,None] # (2,2) expanded to (2,2,1)
In [8]: np.array([[0,1],[3,4]])[:,None,:] # expand to (2,1,2)
这就是广播如何扩展它们:
In [10]: np.broadcast_arrays(ax1,ax2)
Out[10]:
[array([[[0, 0], # block indices
[1, 1]],
[[3, 3],
[4, 4]]]),
array([[[0, 1], # row indices
[0, 1]],
[[3, 4],
[3, 4]]])]
这可能会使模式更清晰:
In [15]: a[ax1,ax2,:] = np.arange(1,5).reshape(2,2,1)
In [16]: a[:,:,0]
Out[16]:
array([[1., 2., 0., 0., 0.],
[3., 4., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 1., 2.],
[0., 0., 0., 3., 4.]])
我有一段 我知道有效的 numpy 代码。我知道这一点,因为我已经在我的通用案例中成功地对其进行了测试。但是,在反复参考文档和反复试验两个小时后,我得出了解决方案。我不明白我怎么知道 凭直觉。
设置:
a = np.zeros((5,5,3))
目标:设置为 1 轴 1 的索引 0,1、轴 2 的 0,1、轴 3 的所有索引和轴 1 的索引 3,4、轴 2 的索引 3,4、轴 3 的所有
更清晰的目标:将块1和2的前两行设置为1,将块3和4的后两行设置为1
结果:
ax1 =np.array([np.array([0,1]),np.array([3,4])])
ax1 =np.array([x[:,np.newaxis] for x in ax1])
ax2 = np.array([[[0,1]],[[3,4]]])
a[ax1,ax2,:] = 1
a
输出:
array([[[1., 1., 1.],
[1., 1., 1.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[1., 1., 1.],
[1., 1., 1.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[1., 1., 1.],
[1., 1., 1.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[1., 1., 1.],
[1., 1., 1.]]])
我倾向于相信我应该能够查看相关矩阵的形状、索引的形状和索引操作以直观地了解输出。但是,我无法将这个故事放在一起。比如,它正在改变的子空间的最终形状是什么? 您如何解释它的工作原理?
形状:
input: (5, 5, 3)
ind1: (2, 2, 1)
ind2: (2, 1, 2)
final_op: input[ind1, ind2, :]
有形状
ind1: (2, 2, 1)
ind2: (2, 1, 2)
他们 broadcast
一起 select a (2,2,2) space
In [4]: ax1
Out[4]:
array([[[0],
[1]],
[[3],
[4]]])
In [5]: ax2
Out[5]:
array([[[0, 1]],
[[3, 4]]])
因此对于第一个维度(块),它是 selecting 块 0、1、3 和 4。在第二个维度中,它也是 selecting 这些行。
前 2 个块的前 2 行和后 2 个块的后 2 行加在一起。这就是结果中出现 1 的位置。
创建索引数组的更简单方法:
In [7]: np.array([[0,1],[3,4]])[:,:,None] # (2,2) expanded to (2,2,1)
In [8]: np.array([[0,1],[3,4]])[:,None,:] # expand to (2,1,2)
这就是广播如何扩展它们:
In [10]: np.broadcast_arrays(ax1,ax2)
Out[10]:
[array([[[0, 0], # block indices
[1, 1]],
[[3, 3],
[4, 4]]]),
array([[[0, 1], # row indices
[0, 1]],
[[3, 4],
[3, 4]]])]
这可能会使模式更清晰:
In [15]: a[ax1,ax2,:] = np.arange(1,5).reshape(2,2,1)
In [16]: a[:,:,0]
Out[16]:
array([[1., 2., 0., 0., 0.],
[3., 4., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 1., 2.],
[0., 0., 0., 3., 4.]])